Skip to the content.

Teams Bot App 用户互动

上一篇文章我们解析了 teams bot 的主体代码逻辑,深入的了解它是怎么运作起来的。我们这篇文章来详细讲一下 adaptive card 在 Teams 里的互动,我们用上一个 app 里的 learn 卡片为例。

我们先运行我们的 Hello World Bot,然后给bot发送 learn 文字后,会等到一个回复的卡片,卡片上的 Like Count 是 0,我们点击一下 “I Like This!” 按钮。

TeamsTookkit

稍等 1,2 秒后,我们就可以看到这个卡片的刷新了,Like Count 变成了 1。

TeamsTookkit

再多点击几次后,数字会一直增加。

TeamsTookkit

这实际上就让 bot 和用户之间有了一种互动,用户可以通过 adaptive card 上的按钮和 bot 进行沟通。

我们来看一下这是怎么做到的。先打开 learn.json 文件,看看这个卡片有什么特别的地方。

TeamsTookkit

可以看到,在卡片的json文件中,那个数字是一个 placeholder ${likeCount},我们后面会讲它是怎么和代码联动的。对于 “I Like This!” 按钮,它的 type 是 Action.Execute,verb 是 userlike,fallback 是 Action.Submit,看到这里我们可以隐隐约约感觉到它像是给 bot 发了一个指令,让bot 去 execute 一个叫 userlike的指令。

    {
      "type": "Action.Execute",
      "title": "I Like This!",
      "verb": "userlike",
      "fallback": "Action.Submit"
    }

我们再来看一下 teamsBot.ts 里的代码,看看它是如何和 adaptive card 联动的。由于这个文件比较长,我挑了和这个操作相关的代码,让大家看得更加清楚简单一些。

import rawLearnCard from "./adaptiveCards/learn.json";

export interface DataInterface {
  likeCount: number;
}

export class TeamsBot extends TeamsActivityHandler {
  // record the likeCount
  likeCountObj: { likeCount: number };

  constructor() {
    super();

    this.likeCountObj = { likeCount: 0 };

    this.onMessage(async (context, next) => {
      let txt = context.activity.text;
      switch (txt) {
        case "learn": {
          this.likeCountObj.likeCount = 0;
          const card = AdaptiveCards.declare<DataInterface>(rawLearnCard).render(this.likeCountObj);
          await context.sendActivity({ attachments: [CardFactory.adaptiveCard(card)] });
          break;
        }
      }
    });
  }

  async onAdaptiveCardInvoke(
    context: TurnContext,
    invokeValue: AdaptiveCardInvokeValue
  ): Promise<AdaptiveCardInvokeResponse> {
    // The verb "userlike" is sent from the Adaptive Card defined in adaptiveCards/learn.json
    if (invokeValue.action.verb === "userlike") {
      this.likeCountObj.likeCount++;
      const card = AdaptiveCards.declare<DataInterface>(rawLearnCard).render(this.likeCountObj);
      await context.updateActivity({
        type: "message",
        id: context.activity.replyToId,
        attachments: [CardFactory.adaptiveCard(card)],
      });
      return { statusCode: 200, type: undefined, value: undefined };
    }
  }
}

首先代码里先申明了一个 interface DataInterface,这个主要是为了填充 adaptive card 里的那个placeholder ${likeCount} 所使用。

class TeamsBot 里先弄了一个 likeCountObj: { likeCount: number }likeCountObject 实际上是一个 interface DataInterface 的实例,它记录了一共被 like 了几次,我觉得这句改成 likeCountObj: DataInterface; 更加清楚,所以我 raise 了一个 pr 给微软产品组 https://github.com/OfficeDev/TeamsFx-Samples/pull/491,看看能不能 merge 成功。

TeamsBot 的构造函数中,当用户发送了 learn 文字后,新建了一个 card,并且把当前的 like count 值填入到 card 中。由于 DataInterface 里的 likeCount 的名字和 json 里的placeholder 的名字 ${likeCount} 一致,所以这个 placeholder 就被赋值了 0。

const card = AdaptiveCards.declare<DataInterface>(rawLearnCard).render(this.likeCountObj);

然后就把卡片加到 activity 里,发送给用户。

await context.sendActivity({ attachments: [CardFactory.adaptiveCard(card)] });

当用户点击的 “I Like This!” 按钮后,onAdaptiveCardInvoke() 函数被触发,可以从代码清楚的看到,如果 verbuserlike,就把like计数器加一,然后通过 context.updateActivity() 来更新这个卡片。

看到这里我想大家已经清楚的明白了前后的逻辑和他们关联的方式。那我们就模仿这个来扩展一下,我们打开 learn.json,在 “I Like This!” 后增加另一个按钮 “Reset Like Count”

    {
      "type": "Action.Execute",
      "title": "Reset Like Count",
      "verb": "resetlike",
      "fallback": "Action.Submit"
    },

然后在 teamsBot.ts 文件里刚才处理 userlike 的后面再加上一段:

    if (invokeValue.action.verb === "userlike") {
        ...
    }
    else if (invokeValue.action.verb === "resetlike") {
      this.likeCountObj.likeCount == 0;
      const card = AdaptiveCards.declare<DataInterface>(rawLearnCard).render(this.likeCountObj);
      await context.updateActivity({
        type: "message",
        id: context.activity.replyToId,
        attachments: [CardFactory.adaptiveCard(card)],
      });
      return { statusCode: 200, type: undefined, value: undefined };
    }

运行程序后,就能看到多了一个按钮,点击 “Reset Like Count” 按钮后,就能够重置 like 计数器。

TeamsTookkit

所以 teams bot 并不是一个非常难的东西,通过我们对代码一步步的解析,然后做一些简单修改,希望各位读者大致明白了 bot 运行的机理。

Written on October 3, 2022