Iniciar acciones con extensiones de mensaje

Importante

Los artículos de esta sección se basan en el SDK de Bot Framework v3. Si está buscando documentación actual (versión 4.6 o posterior del SDK), consulte la sección Interacciones orientadas a tareas con extensiones de mensaje .

Las extensiones de mensajes basados en acciones permiten a los usuarios desencadenar acciones en servicios externos mientras están en Teams.

La captura de pantalla es un ejemplo que muestra la tarjeta de extensión de mensaje.

Agregar una extensión de mensaje a la aplicación

Una extensión de mensaje es un servicio hospedado en la nube que escucha las solicitudes del usuario y responde con datos estructurados, como una tarjeta. Puede integrar el servicio con Microsoft Teams mediante objetos de Bot Framework Activity . Nuestras extensiones .NET y Node.js para el SDK de Bot Builder pueden ayudarle a agregar la funcionalidad de extensión de mensaje a la aplicación.

Captura de pantalla que muestra la extensión de mensajería basada en acciones en Teams.

Registrarse en Bot Framework

Primero debe registrar un bot con Microsoft Bot Framework. El id. de aplicación de Microsoft y los puntos de conexión de devolución de llamada para el bot, tal como se definen allí, se usan en la extensión de mensaje para recibir y responder a las solicitudes de los usuarios. Recuerde habilitar el canal de Microsoft Teams para su bot.

Tome nota del id. de la aplicación bot y la contraseña de la aplicación. Debe proporcionar el id. de la aplicación en el manifiesto de la aplicación.

Actualizar el manifiesto de la aplicación

Al igual que con los bots y las pestañas, el manifiesto de la aplicación se actualiza para incluir las propiedades de la extensión de mensaje. Estas propiedades rigen cómo aparece y se comporta la extensión de mensaje en el cliente de Microsoft Teams. Las extensiones de mensajes se admiten a partir del manifiesto v1.0.

Declare su extensión de mensaje

Para agregar una extensión de mensaje, incluya una nueva estructura JSON de nivel superior en el manifiesto con la composeExtensions propiedad. Está limitado a crear una única extensión de mensaje para la aplicación.

Nota

El manifiesto hace referencia a las extensiones de mensaje como composeExtensions. Esto es para mantener la compatibilidad con versiones anteriores.

La definición de extensión es un objeto con la siguiente estructura:

Nombre de propiedad Finalidad ¿Obligatoria?
botId El id. de aplicación de Microsoft único para el bot registrado con Bot Framework. Por lo general, debe ser el mismo que el identificador de la aplicación de Teams general.
scopes Matriz que declara si esta extensión se puede agregar a personal ámbitos u team otros (o ambos).
canUpdateConfiguration Habilita el elemento de menú Configuración . No
commands Matriz de comandos que admite esta extensión de mensajería. Tienes un límite de 10 comandos.

Nota

Si establece la canUpdateConfiguration propiedad true en el manifiesto de la aplicación, puede mostrar el elemento de menú Configuración para la extensión de mensajería. Para habilitar la configuración, también debe controlar onQuerySettingsUrl y onSettingsUpdate.

Definir comandos

Su extensión de mensaje debe declarar un comando, que aparece cuando el usuario selecciona su aplicación en el botón Más opciones () en el cuadro de redacción.

Captura de pantalla es un ejemplo que muestra una lista de extensiones de mensaje en Teams.

En el manifiesto de la aplicación, el elemento de comando es un objeto con la siguiente estructura:

Nombre de propiedad Finalidad ¿Obligatoria? Versión mínima del manifiesto
id Id. exclusivo que asigna a este comando. La solicitud del usuario incluye este identificador. 1,0
title Nombre del comando. Este valor aparece en la interfaz de usuario. 1,0
description Texto de ayuda que indica lo que hace este comando. Este valor aparece en la interfaz de usuario. 1,0
type Establezca el tipo de comando. Los valores posibles incluyen query y action. Si no está presente, el valor predeterminado se establece en query. No 1,4
initialRun Parámetro opcional, que se usa con query comandos. Si se establece en true, indica que este comando debe ejecutarse tan pronto como el usuario elija este comando en la interfaz de usuario. No 1,0
fetchTask Parámetro opcional, que se usa con action comandos. Establézcalo en true para capturar una tarjeta adaptativa o una dirección URL web que se mostrará en el módulo de tareas. Esto se usa cuando la entrada del action comando es dinámica en lugar de un conjunto estático de parámetros. Tenga en cuenta que si se establece en true, se omite la lista de parámetros estáticos del comando. No 1,4
parameters Lista estática de parámetros para el comando. 1,0
parameter.name El nombre del parámetro. Esto se envía a su servicio en la solicitud del usuario. 1,0
parameter.description Describe los propósitos de este parámetro y un ejemplo del valor que debe proporcionarse. Este valor aparece en la interfaz de usuario. 1,0
parameter.title Título o etiqueta de parámetro breve y fácil de usar. 1,0
parameter.inputType Establezca el tipo de entrada necesaria. Los valores posibles incluyen text, textarea, number, date, time, toggle, . El valor predeterminado se establece en text. No 1,4
context Matriz opcional de valores que define el contexto en el que está disponible la acción del mensaje. Los valores posibles son message, compose, o commandBox. El valor predeterminado es ["compose", "commandBox"]. No 1,5

Extensiones de mensaje de tipo de acción

Para iniciar acciones desde una extensión de mensaje, establezca el type parámetro en action. Una sola extensión de mensaje puede tener hasta 10 comandos diferentes e incluir varios comandos basados en búsquedas y en acciones.

Ejemplo de manifiesto de aplicación completo

El código siguiente es un ejemplo de un manifiesto con un comando search y 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 acciones a partir de mensajes

Puede iniciar acciones desde el área de redacción de mensajes y también desde un mensaje utilizando la extensión de mensaje, lo que le permite enviar el contenido del mensaje al bot para su procesamiento. Opcionalmente, puede responder a ese mensaje mediante el método descrito en Responder para enviar. La respuesta se incluye como una respuesta al mensaje, que los usuarios pueden editar antes de enviar.

Los usuarios pueden acceder a la extensión de mensaje desde la opción Realizar acción del menú de desbordamiento ... , como se muestra en la siguiente imagen:

Captura de pantalla que describe cómo iniciar una acción desde un mensaje.

Para permitir que la extensión de mensaje funcione a partir de un mensaje, agregue el parámetro al objeto de la extensión de mensaje en el context manifiesto de commands la aplicación, como en el ejemplo siguiente. Las cadenas válidas para la context matriz son "message", "commandBox", y "compose". El valor predeterminado es ["compose", "commandBox"]. Consulte la sección definir comandos para obtener detalles completos sobre el 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
    }]
    ...

El código siguiente es un ejemplo del value objeto que contiene los detalles del mensaje que se envía como parte de la composeExtensions solicitud al 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
          }
        }
      ]
    }
  ...

Probar mediante la carga

Puede probar la extensión de mensaje cargando la aplicación. Para obtener más información, consulte Carga de la aplicación en un equipo.

Para abrir la extensión de mensajes, vaya a cualquiera de los chats o canales. Seleccione el botón Más opciones () en el cuadro de redacción y elija la extensión de mensaje.

Recopilar información de los usuarios

Hay tres maneras de recopilar información de un usuario en Teams.

Lista de parámetros estáticos

En este método, todo lo que necesita hacer es definir una lista estática de parámetros en el manifiesto como se muestra en el comando "Create To Do". Para usar este método, asegúrese de fetchTask que está establecido y false de que define los parámetros en el manifiesto.

Cuando un usuario elige un comando con parámetros estáticos, Teams genera un formulario en un módulo de tareas con los parámetros definidos en el manifiesto. Al presionar Enviar, se envía un al composeExtensions/submitAction bot. Para obtener más información sobre el conjunto de respuestas esperado, consulte Responder para enviar.

Entrada dinámica mediante una tarjeta adaptativa

Con este método, el servicio puede definir una tarjeta adaptativa personalizada para recopilar la entrada del usuario. Para este enfoque, establezca el fetchTask parámetro true en el manifiesto. Si establece fetchTask en , se omiten los trueparámetros estáticos definidos para el comando.

En este método, el servicio recibe un composeExtensions/fetchTask evento y responde con una respuesta de módulo de tareas basada en tarjeta adaptable. A continuación se muestra un ejemplo de respuesta con una tarjeta adaptable:

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

El bot también puede responder con una respuesta de autenticación o configuración si el usuario necesita autenticar o configurar la extensión antes de obtener la entrada del usuario.

Entrada dinámica mediante una vista web

En este método, el servicio puede mostrar un <iframe> widget basado para mostrar cualquier interfaz de usuario personalizada y recopilar la entrada del usuario. Para este enfoque, establezca el fetchTask parámetro true en el manifiesto.

Al igual que en el flujo de tarjeta adaptable, el servicio envía un fetchTask evento y responde con una respuesta de módulo de tareas basada en dirección URL. A continuación se muestra un ejemplo de respuesta con una tarjeta adaptable:

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

Solicitar la instalación del bot conversacional

Si la aplicación contiene un bot de conversación, asegúrese de que está instalado en la conversación antes de cargar el módulo de tareas para obtener más contexto para el módulo de tareas. Por ejemplo, puede que necesite capturar la lista para rellenar un control selector de personas o la lista de canales de un equipo.

Para facilitar este flujo, cuando la extensión de mensaje reciba la composeExtensions/fetchTask llamada por primera vez, compruebe si el bot está instalado en el contexto actual. Puede obtener esto, intentando la llamada de obtener la lista. Por ejemplo, si el bot no está instalado, devuelve una tarjeta adaptativa con una acción que solicita al usuario que instale el bot. El usuario debe tener permiso para instalar aplicaciones en esa ubicación. Si no se puede instalar, en el mensaje se le pedirá que se ponga en contacto con el administrador.

Este es un ejemplo de la respuesta:

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

Una vez que el usuario completa la instalación, el bot recibe otro mensaje de invocación con name = composeExtensions/submitAction y value.data.msteams.justInTimeInstall = true.

Este es un ejemplo de la invocación:

{
  "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 a la invocación con la misma respuesta de tarea con la que ha respondido, si se instaló el bot.

Respuesta para enviar

Una vez que un usuario completa la entrada de su entrada, el bot recibe un composeExtensions/submitAction evento con el ID de comando y los valores de parámetro establecidos.

Estas son las diferentes respuestas esperadas a una .submitAction

Respuesta del módulo de tareas

La respuesta del módulo de tareas se usa cuando la extensión necesita encadenar diálogos para obtener más información. La respuesta es la misma que se fetchTask mencionó anteriormente.

Compose extensiones auth/config response

Compose extensiones La respuesta de autenticación/configuración se usa cuando la extensión necesita autenticarse o configurarse para continuar. Para obtener más información, consulte la sección de autenticación en la sección de búsqueda.

Respuesta del resultado de compose extensiones

Compose respuestas al resultado de las extensiones se usa para insertar una tarjeta en el cuadro de redacción como resultado del comando. Es la misma respuesta que se usa en el comando de búsqueda, pero está limitada a una tarjeta o un resultado de la 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 con un mensaje de tarjeta adaptable enviado desde un bot

Responda a la acción de envío insertando un mensaje con una tarjeta adaptativa en el canal con un bot. El usuario puede obtener una vista previa del mensaje antes de enviarlo y, potencialmente, editar o interactuar con él también. Esto puede ser útil en escenarios en los que necesita recopilar información de los usuarios antes de crear una respuesta de tarjeta adaptable. El siguiente escenario muestra cómo puede usar este flujo para configurar un sondeo sin incluir los pasos de configuración en el mensaje del canal.

  1. El usuario selecciona la extensión de mensaje para desencadenar el módulo de tareas.
  2. El usuario utiliza el módulo de tareas para configurar el sondeo.
  3. Después de enviar el módulo de tareas de configuración, la aplicación usa la información proporcionada en el módulo de tareas para crear una tarjeta adaptativa y enviarla como respuesta botMessagePreview al cliente.
  4. A continuación, el usuario puede obtener una vista previa del mensaje de tarjeta adaptable antes de que el bot lo inserte en el canal. Si el bot aún no es miembro del canal, al hacer clic se Send agrega el bot.
  5. La interacción con la tarjeta adaptativa cambia el mensaje antes de enviarlo.
  6. Una vez que el usuario selecciona Send, el bot publica el mensaje en el canal.

Nota

  • Debe activityPreview contener una message actividad con exactamente un accesorio de tarjeta adaptable.
  • Outlook no admite responder con un mensaje de tarjeta adaptable enviado desde un bot.

Para habilitar este flujo, el módulo de tareas debe responder como en el ejemplo siguiente, que presenta el mensaje de vista previa al usuario:

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

Su extensión de mensaje debe responder a dos nuevos tipos de interacciones value.botMessagePreviewAction = "send" y value.botMessagePreviewAction = "edit". El código siguiente es un ejemplo del value objeto que necesita procesar:

{
  "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" }
      }
    ],
  }
}

Al responder a la edit solicitud, debe responder con una respuesta con los task valores rellenados con la información que envió el usuario. Al responder a la send solicitud, debes enviar un mensaje al canal que contiene la tarjeta adaptativa finalizada.

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);
        }
    });

Vea también

Ejemplos de Bot Framework