Conversar com um bot do Microsoft Teams

Importante

Este artigo é baseado no SDK do Bot Framework v3. Se você estiver procurando a documentação atual versão 4.6 ou posterior do SDK, consulte a seção bots de conversação .

Uma conversa é uma série de mensagens enviadas entre seu bot e um ou mais usuários. Há três tipos de conversas (também chamados de escopos) no Teams:

  • teams Também chamado de conversas de canal, visível para todos os membros do canal.
  • personal conversas entre bots e um único usuário.
  • groupChat converse entre um bot e dois ou mais usuários.

Um bot se comporta ligeiramente diferente dependendo do tipo de conversa na qual ele está envolvido:

Para que o bot funcione em um escopo específico, ele deve ser listado como suporte a esse escopo no manifesto. Os escopos são definidos e discutidos ainda mais na Referência do manifesto.

Mensagens proativas

Os bots podem participar de uma conversa ou iniciar uma. A maior parte da comunicação é em resposta a outra mensagem. Se um bot iniciar uma conversa, será chamado de mensagem proativa. Os exemplos incluem:

  • Mensagem de boas-vindas
  • Notificações de eventos
  • Mensagens de sondagem

Noções básicas sobre conversas

Cada mensagem é um Activity do tipo messageType: message. Quando um usuário envia uma mensagem, o Teams posta a mensagem em seu bot; especificamente, ele envia um objeto JSON para o ponto de extremidade de mensagens do seu bot. Seu bot examina a mensagem para determinar seu tipo e responde adequadamente.

Os bots também dão suporte a mensagens de estilo de evento. Para obter mais informações, consulte Manipular eventos de bot no Microsoft Teams. No momento, não há suporte para fala.

As mensagens são, normalmente, as mesmas em todos os escopos, mas há diferenças em como o bot é acessado na interface do usuário e diferenças nos bastidores, sobre as quais você precisará saber.

A conversa básica é tratada por meio do conector Bot Framework, uma única API REST para permitir que seu bot se comunique com o Teams e outros canais. O Bot Builder SDK fornece acesso fácil a essa API, funcionalidade adicional para gerenciar o fluxo e o estado da conversa e maneiras simples de incorporar serviços cognitivos, como o NLP (processamento de linguagem natural).

Conteúdo da mensagem

Seu bot pode enviar rich text, imagens e cartões. Os usuários podem enviar rich text e imagens para seu bot. Você pode especificar o tipo de conteúdo que seu bot pode manipular na página de configurações do Microsoft Teams para o bot.

Formatar Do usuário para o bot Do bot para o usuário Observações
Rich text
Imagens Máximo de 1024×1024 MB e 1 MB no formato PNG, JPEG ou GIF; não há suporte para GIF animado.
Cartões Consulte a Referência de cartão do Teams para obter cartões com suporte.
Emojis Atualmente, o Teams dá suporte a emojis por meio de UTF-16, como U+1F600, para a detecção facial.

Para obter mais informações sobre os tipos de interação de bot suportados pelo Bot Framework, nos quais os bots nas equipes se baseiam, consulte a documentação do Bot Framework sobre fluxo de conversação e conceitos relacionados na documentação do SDK do Bot Builder para .NET e do SDK do Bot Builder para Node.js.

Formatação de mensagem

Você pode definir a propriedade opcional TextFormat de um message para controlar como o conteúdo de texto da mensagem é renderizado. Consulte Mensagem de formatação para obter uma descrição detalhada da formatação com suporte em mensagens de bot. Você pode definir a propriedade opcional TextFormat para controlar como o conteúdo de texto da mensagem é renderizado.

Para obter informações detalhadas sobre como o Teams dá suporte à formatação de texto em equipes, consulte Formatação de texto em mensagens de bot.

Para obter mais informações sobre formatação de cartões em mensagens, consulte Formatação de cartão.

Mensagens de imagem

As imagens são enviadas adicionando anexos a uma mensagem. Você pode encontrar mais informações sobre anexos na Bot Framework documentação.

As imagens podem ter no máximo 1024×1024 MB e 1 MB no formato PNG, JPEG ou GIF; NÃO há suporte para GIF animado.

Recomendamos que você especifique a altura e a largura de cada imagem usando XML. Se você usar Markdown, o tamanho da imagem usará como padrão 256×256. Por exemplo:

  • Use<img src="http://aka.ms/Fo983c" alt="Duck on a rock" height="150" width="223"></img>
  • Não use ![Duck on a rock](http://aka.ms/Fo983c).

Recebendo mensagens

Dependendo de quais escopos são declarados, seu bot pode receber mensagens nos seguintes contextos:

  • chat pessoal Os usuários podem interagir em uma conversa privada com um bot selecionando o bot adicionado no histórico de chat ou digitando seu nome ou ID do aplicativo na caixa Para: em um novo chat.
  • Canais Um bot pode ser mencionado ("@botname") em um canal se tiver sido adicionado à equipe. Observe que respostas adicionais a um bot em um canal exigem a menção do bot. Ele não responderá às respostas em que não for mencionado.

Para mensagens de entrada, o bot recebe um objeto Atividade do tipo messageType: message. Embora o objeto Activity possa conter outros tipos de informações, como atualizações do canal enviadas ao bot, o tipo message representa a comunicação entre o bot e o usuário.

O bot recebe uma carga que contém a mensagem Text do usuário e outras informações sobre o usuário, a origem da mensagem e as informações do Teams. Observação:

  • timestamp A data e a hora da mensagem em Tempo Universal Coordenado (UTC).
  • localTimestamp A data e a hora da mensagem no fuso horário do remetente.
  • channelId Sempre "msteams". Isso se refere a um canal do Bot Framework, não a um canal de equipes.
  • from.id Uma ID exclusiva e criptografada para esse usuário para seu bot; adequada como uma chave se seu aplicativo precisar armazenar dados do usuário. É exclusiva para seu bot e não pode ser usada diretamente fora da instância do bot de qualquer maneira significativa para identificar esse usuário.
  • channelData.tenant.id A ID do locatário do usuário.

Observação

from.id é exclusivo para seu bot e não pode ser usado diretamente fora da instância do bot de qualquer maneira significativa para identificar esse usuário.

Combinando canal e interações privadas com seu bot

Ao interagir em um canal, seu bot deve ser inteligente em colocar determinadas conversas offline com um usuário. Por exemplo, suponha que um usuário esteja tentando coordenar uma tarefa complexa, como agendar com um conjunto de membros da equipe. Em vez de ter toda a sequência de interações visíveis para o canal, considere enviar uma mensagem de chat pessoal para o usuário. Seu bot deve ser capaz de fazer facilmente a transição do usuário entre conversas pessoais e de canal sem perder o estado.

Observação

Não se esqueça de atualizar o canal quando a interação for concluída para notificar os outros membros da equipe.

Exemplo de esquema de entrada completo

{
    "type": "message",
    "id": "1485983408511",
    "timestamp": "2017-02-01T21:10:07.437Z",
    "localTimestamp": "2017-02-01T14:10:07.437-07:00",
    "serviceUrl": "https://smba.trafficmanager.net/amer/",
    "channelId": "msteams",
    "from": {
        "id": "29:1XJKJMvc5GBtc2JwZq0oj8tHZmzrQgFmB39ATiQWA85gQtHieVkKilBZ9XHoq9j7Zaqt7CZ-NJWi7me2kHTL3Bw",
        "name": "Megan Bowen",
        "aadObjectId": "7faf8ab2-3d56-4244-b585-20c8a42ed2b8"
    },
    "conversation": {
        "conversationType": "personal",
        "id": "a:17I0kl9EkpE1O9PH5TWrzrLNwnWWcfrU7QZjKR0WSfOpzbfcAg2IaydGElSo10tVr4C7Fc6GtieTJX663WuJCc1uA83n4CSrHSgGBj5XNYLcVlJAs2ZX8DbYBPck201w-"
    },
    "recipient": {
        "id": "28:c9e8c047-2a74-40a2-b28a-b162d5f5327c",
        "name": "Teams TestBot"
    },
    "textFormat": "plain",
    "text": "Hello Teams TestBot",
    "entities": [
      { 
        "locale": "en-US",
        "country": "US",
        "platform": "Windows",
        "timezone": "America/Los_Angeles",
        "type": "clientInfo"
      }
    ],
    "channelData": {
        "tenant": {
            "id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
        }
    },
    "locale": "en-US"
}

Observação

Às vezes, o campo de texto para mensagens de entrada contém menções. Verifique e desmarque-os corretamente. Para obter mais informações, Menções.

Dados do canal do Teams

O objeto channelData contém informações específicas do Teams e é a fonte definitiva para IDs de equipe e canal. Você deve armazenar em cache e usar essas IDs como chaves para armazenamento local.

Um objeto channelData típico em uma atividade enviada ao bot contém as seguintes informações:

  • eventType tipo de evento do Teams; passado somente em casos de eventos de modificação de canal.
  • tenant.idMicrosoft Entra ID do locatário; passado em todos os contextos.
  • team Passado somente em contextos de canal, não no chat pessoal.
  • channel Passado somente em contextos de canal quando o bot é mencionado ou para eventos em canais em equipes em que o bot foi adicionado.
  • channelData.teamsTeamId preterido. Essa propriedade é incluída somente para compatibilidade com versões anteriores.
  • channelData.teamsChannelId preterido. Essa propriedade é incluída somente para compatibilidade com versões anteriores.

Exemplo de objeto channelData (evento channelCreated)

"channelData": {
    "eventType": "channelCreated",
    "tenant": {
        "id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
    },
    "channel": {
        "id": "19:693ecdb923ac4458a5c23661b505fc84@thread.skype",
        "name": "My New Channel"
    },
    "team": {
        "id": "19:693ecdb923ac4458a5c23661b505fc84@thread.skype"
    }
}

Exemplo do .NET

O Microsoft.Bot.Connector.Teams fornece um objeto TeamsChannelData especializado, que expõe propriedades para acessar informações específicas do Teams.

TeamsChannelData channelData = activity.GetChannelData<TeamsChannelData>();
string tenantId = channelData.Tenant.Id;

Enviando respostas para mensagens

Para responder a uma mensagem existente, chame ReplyToActivity no .NET ou session.send em Node.js. O SDK do Bot Builder lida com todos os detalhes.

Se você optar por usar a API REST, também poderá chamar o ponto de extremidade /v3/conversations/{conversationId}/activities/{activityId}.

O próprio conteúdo da mensagem pode conter texto simples ou alguns dos Bot Framework fornecidos cards e ações de cartão.

Observe que, em seu esquema de saída, você sempre deve usar o mesmo serviceUrl que o que você recebeu. Lembre-se de que o valor de serviceUrl tende a ser estável, mas pode mudar. Quando uma nova mensagem chega, o bot deve verificar seu valor armazenado de serviceUrl.

Atualizando mensagens

Em vez de suas mensagens serem instantâneos estáticos de dados, o bot pode atualizar dinamicamente as mensagens embutidas depois de enviá-las. Você pode usar atualizações dinâmicas de mensagens para cenários como atualizações de votação, modificação de ações disponíveis após um pressionamento de botão ou qualquer outra alteração de estado assíncrona.

A nova mensagem não precisa corresponder ao original no tipo. Por exemplo, se a mensagem original continha um anexo, a nova mensagem pode ser uma mensagem de texto.

Observação

Você pode atualizar apenas o conteúdo enviado em mensagens de anexo único e layouts de carrossel. Não há suporte para a postagem de atualizações em mensagens com vários anexos no layout da lista.

API do REST

Para emitir uma atualização de mensagem, execute uma solicitação PUT no /v3/conversations/<conversationId>/activities/<activityId>/ ponto de extremidade usando uma determinada ID de atividade. Para concluir esse cenário, você deve armazenar em cache a ID da atividade retornada pela chamada POST original.

PUT /v3/conversations/19%3Aja0cu120i1jod12j%40skype.net/activities/012ujdo0128
{
    "type": "message",
    "text": "This message has been updated"
}

Exemplo do .NET

Você pode usar o método UpdateActivityAsync no SDK do Bot Builder para atualizar uma mensagem existente.

public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
  if (activity.Type == ActivityTypes.Message)
  {
    ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
    Activity reply = activity.CreateReply($"You sent {activity.Text} which was {activity.Text.Length} characters");
    var msgToUpdate = await connector.Conversations.ReplyToActivityAsync(reply);
    Activity updatedReply = activity.CreateReply($"This is an updated message");
    await connector.Conversations.UpdateActivityAsync(reply.Conversation.Id, msgToUpdate.Id, updatedReply);
  }
}

Exemplo de Node.js

Você pode usar o método session.connector.update no SDK do Bot Builder para atualizar uma mensagem existente.

function sendCardUpdate(bot, session, originalMessage, address) {

  var origAttachment = originalMessage.data.attachments[0];
  origAttachment.content.subtitle = 'Assigned to Larry Jin';

  var updatedMsg = new builder.Message()
    .address(address)
    .textFormat(builder.TextFormat.markdown)
    .addAttachment(origAttachment)
    .toMessage();

  session.connector.update(updatedMsg, function(err, addresses) {
    if (err) {
      console.log(`Could not update the message`);
    }
  });
}

Iniciando uma conversa (mensagens proativas)

Você pode criar uma conversa pessoal com um usuário ou iniciar uma nova cadeia de resposta em um canal para o bot de equipe. Isso permite que você envie uma mensagem ao usuário ou aos usuários sem que eles iniciem primeiro o contato com o bot. Para saber mais, confira os seguintes artigos:

Para obter mais informações sobre conversas iniciadas por bots, consulte mensagens proativas para bots.

Excluindo mensagens

As mensagens podem ser excluídas usando o connector.delete() método no SDK do BotBuilder.

bot.dialog('BotDeleteMessage', function (session: builder.Session) {
  var msg = new teams.TeamsMessage(session).text("Bot will delete this message in 5 sec.")
  bot.send(msg, function (err, response) {
    if (err) {
      console.log(err);
      session.endDialog();
    }

    console.log('Proactive message response:');
    console.log(response);
    console.log('---------------------------------------------------')
    setTimeout(function () {
      var activityId: string = null;
      var messageAddress: builder.IChatConnectorAddress = null;
      if (response[0]){
        messageAddress = response[0];
        activityId = messageAddress.id;
      }

      if (activityId == null)
      {
        console.log('Message failed to send.');
        session.endDialog();
        return;
      }

      // Bot delete message
      let address: builder.IChatConnectorAddress  = {
        channelId: 'msteams',
        user: messageAddress.user,
        bot: messageAddress.bot,
        id : activityId,
        serviceUrl : (<builder.IChatConnectorAddress>session.message.address).serviceUrl,
        conversation: {
          id: session.message.address.conversation.id
        }
      };

      connector.delete(address, function (err) {
        if (err)
        {
          console.log(err);
        }
        else
        {
          console.log("Message: " + activityId + " deleted successfully.");
        }

        // Try editing deleted message would fail
        var newMsg = new builder.Message().address(address).text("To edit message.");
        connector.update(newMsg.toMessage(), function (err, address) {
          if (err)
          {
            console.log(err);
            console.log('Deleted message can not be edited.');
          }
          else
          {
            console.log("There is something wrong. Message: " + activityId + " edited successfully.");
            console.log(address);
          }

          session.endDialog();
        });
      });
    }, 5000);
  });
})