Teams Bot开发系列:Teams的Activity处理
上一篇文章讲了activity处理的流程,我们bot的核心处理逻辑放在ActivityHandler的子类里,通过重载OnMessageActivityAsync()
方法来实现。
这篇文章我来讲一下对于Teams的bot来说,整个处理的逻辑会有哪些不同点。
通过之前的文章,大家应该已经知道,Teams bot是Azure bot service支持的众多bot聊天平台里的一种channel(注意:这里的channel指bot service里的channel,和Teams里的channel是完全不同的概念)。但是Teams实际上提供了很多特有的事件和动作。使用bot sdk的通用模型,我们当然可以处理这些事情,但是Teams作为微软的主打产品,微软的bot sdk当然要为它提供更多的开发便利性。
SDK提供了一个针对Teams的ActivityHandler。这个handler有下面这些特殊的ConversationUpdateActivity的处理函数
事件 | 函数 | 说明 |
---|---|---|
channelCreated |
OnTeamsChannelCreatedAsync
|
当Teams的channel被创建 |
channelDeleted |
OnTeamsChannelDeletedAsync
|
当Teams的channel被删除 |
channelRenamed |
OnTeamsChannelRenamedAsync
|
当Teams的channel被重命名 |
teamRenamed |
OnTeamsTeamRenamedAsync
|
当Teams的一个team被重命名 |
MembersAdded |
OnTeamsMembersAddedAsync
|
当Teams的一个team中有新用户加入 |
MembersRemoved |
OnTeamsMembersRemovedAsync
|
当Teams的一个team中有用户被移除 |
除了ConversationUpdateActivity这些Teams的特殊事件,handler还提供了一些Teams特有的invoke动作的处理
Invoke类型 | 函数 | 说明 |
---|---|---|
CardAction.Invoke |
OnTeamsCardActionInvokeAsync
|
关于卡片的动作,比如卡片上一个按钮被点击了 |
fileConsent/invoke |
OnTeamsFileConsentAcceptAsync
|
用户同意了上传文件 |
fileConsent/invoke |
OnTeamsFileConsentAsync
|
用户要上传文件. |
fileConsent/invoke |
OnTeamsFileConsentDeclineAsync
|
用户拒绝了上传文件. |
actionableMessage/executeAction |
OnTeamsO365ConnectorCardActionAsync
|
O365连接器的卡片动作 |
signin/verifyState |
OnTeamsSigninVerifyStateAsync
|
登入验证状态 |
task/fetch |
OnTeamsTaskModuleFetchAsync
|
Teams的Task Module的获取 |
task/submit |
OnTeamsTaskModuleSubmitAsync
|
Teams的Task Module的提交 |
上面表格中的OnTeamsFileConsentAsync
实际上是OnTeamsFileConsentAcceptAsync
和OnTeamsFileConsentDeclineAsync
的一个综合处理,你可以重载OnTeamsFileConsentAsync
,或者分别重载 accept 和 decline 函数。下面的sdk代码可以让你有直观的了解
protected virtual async Task<InvokeResponse> OnTeamsFileConsentAsync(ITurnContext<IInvokeActivity> turnContext, FileConsentCardResponse fileConsentCardResponse, CancellationToken cancellationToken)
{switch (fileConsentCardResponse.Action){case "accept":await OnTeamsFileConsentAcceptAsync(turnContext, fileConsentCardResponse, cancellationToken).ConfigureAwait(false);return CreateInvokeResponse();case "decline":await OnTeamsFileConsentDeclineAsync(turnContext, fileConsentCardResponse, cancellationToken).ConfigureAwait(false);return CreateInvokeResponse();default:throw new InvokeResponseException(HttpStatusCode.BadRequest, $"{fileConsentCardResponse.Action} is not a supported Action.");}
}
对于喜欢把问题研究透彻的朋友可能会问,Teams的ActivityHandler到底是怎么处理的?让我们跳入sdk源代码一探究竟。
public class TeamsActivityHandler : ActivityHandler
{protected override async Task<InvokeResponse> OnInvokeActivityAsync(ITurnContext<IInvokeActivity> turnContext, CancellationToken cancellationToken){...switch (turnContext.Activity.Name){case "fileConsent/invoke":return await OnTeamsFileConsentAsync(turnContext, SafeCast<FileConsentCardResponse>(turnContext.Activity.Value), cancellationToken).ConfigureAwait(false);case "task/fetch":return CreateInvokeResponse(await OnTeamsTaskModuleFetchAsync(turnContext, SafeCast<TaskModuleRequest>(turnContext.Activity.Value), cancellationToken).ConfigureAwait(false));case "task/submit":return CreateInvokeResponse(await OnTeamsTaskModuleSubmitAsync(turnContext, SafeCast<TaskModuleRequest>(turnContext.Activity.Value), cancellationToken).ConfigureAwait(false));......default:return await base.OnInvokeActivityAsync(turnContext, cancellationToken).ConfigureAwait(false);}...}protected override Task OnConversationUpdateActivityAsync(ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken){...switch (channelData.EventType){case "channelCreated":return OnTeamsChannelCreatedAsync(channelData.Channel, channelData.Team, turnContext, cancellationToken);case "channelDeleted":return OnTeamsChannelDeletedAsync(channelData.Channel, channelData.Team, turnContext, cancellationToken);case "channelRenamed":return OnTeamsChannelRenamedAsync(channelData.Channel, channelData.Team, turnContext, cancellationToken);case "teamRenamed":return OnTeamsTeamRenamedAsync(channelData.Team, turnContext, cancellationToken);default:return base.OnConversationUpdateActivityAsync(turnContext, cancellationToken);}...}
}
从上面的代码里可以看到没有什么特别的magic,TeamsActivityHandler重载了OnConversationUpdateActivityAsync
,并且根据channelData.EventType
判断出不同teams的事件,然后调用相应的方法。对于invoke也类似,重载了OnInvokeActivityAsync
,根据turnContext.Activity.Name来调用不同的方法。
回到我们的EchoBot代码,让EchoBot从TeamsActivityHandler
继承下来,然后我们可以添加OnTeamsChannelRenamedAsync
方法。把EchoBot设置到Teams里,修改安装了EchoBot的channel的名字,就可以看到这个方法被促发的。
public class EchoBot : TeamsActivityHandler
{protected virtual Task OnTeamsChannelRenamedAsync(ChannelInfo channelInfo, TeamInfo teamInfo, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken){var replyText = "Channel renamed.";await turnContext.SendActivityAsync(MessageFactory.Text(replyText, replyText), cancellationToken);}
}
Teams Bot开发系列:Teams的Activity处理相关推荐
- Teams Bot开发系列:初识Bot
上次我们讲了Teams Bot开发的概述,讲了Azure Bot Service,Bot Framework SDK和我们自己的bot服务的概念,这篇文章就带大家看看Azure Bot Service ...
- Teams Bot开发系列:Bot验证
我们今天来说一下authentication,authentication一直是一个复杂的问题.bot里的authentication也不简单.我们先来看一个概念:Bot Framework Toke ...
- Teams Bot开发系列:Activity和Turn
这篇文章我们来说一下Activity和Turn这两个bot framework中最重要的两个概念,同时也介绍一下TurnContext和BotAdapter Activity 一个activity是聊 ...
- Teams Bot开发系列:Activity处理流程
上篇文章介绍了什么是Activity,Turn,TurnContext和BotAdapter,这篇文章我们看看这些东西是如何窜起来的,他们是如何处理用户发给bot的消息的. 我们以一个最简单的bot, ...
- Teams Bot开发系列:Middleware
middleware是目前一些framework比较流行的概念,通常一个开发框架需要提供一些可扩展可定制化的功能.所以middleware这种pattern就很实用. 熟悉asp.net core的开 ...
- Teams Bot App 初探
上一篇文章深入讲了incoming webhook.这篇文章我们来看一个稍微复杂点的,正式点的 teams app:bot. 我们先来和之前一样,通过teams toolkit 的 sample ga ...
- 用AzureFunction开发最简单的Teams Bot
之前我有一篇文章讲了如何在azure function上开发最简单的outgoing webhook,收到一些反馈,建议我介绍一下如果在azure function上开发teams bot,那这篇文章 ...
- 在VSCode Remote环境下开发Teams Bot
我使用VS Code开发已经有蛮长一段时间了,时间长了,越来越喜欢VS Code,虽然有些时候会没有传统的VS方便,比如开发Azure Function时你需要编写一下launch.json,而且你需 ...
- 如何开发Teams Bot
很多朋友问我如何开发一个成功的Teams Bot,他们说Bot Framework SDK看起来简单,但是真要的去开发一款成熟的bot,很多地方还是不知道如何使用.我从最早的bot framework ...
最新文章
- 树莓派上传文件到服务器,05_树莓派图片定时上传到服务器
- JavaScript面试系列:JavaScript设计模式之桥接模式和懒加载
- 浏览器无法访问虚拟机的服务器
- PP部分主数据导出SQVI设置
- xshell执行结果到文本_xshell拷贝文件到本地
- RocketMQ的Producer详解之分布式事务消息(代码实现以及过程分析)
- Cookie和Session的作用和工作原理
- Java学习笔记——模块化
- php mysql 操作函数_PHP操作mysql函数详解,mysql和php交互函数
- 数据3分钟丨GitHub开放全世界最大安全咨询数据库;DataBench-T正式开源;甲骨文283亿美元收购Cerner...
- Educational Codeforces Round 47
- 把Alexa工具条改装成木马
- IDEA2017版本的破解方法
- vooc充电原理_OPPO手机充电技术——VOOC技术原理
- 华为智慧屏跟Android,华为智慧屏全力打造智慧生活体验 “智慧屏”时代来临
- 第八届“图灵杯”NEUQ—ACM程序设计竞赛个人赛(同步赛)
- 好看的网站发布导航页HTML源码
- 第十四届蓝桥杯模拟赛c++ 试题 I
- wordpress.mu
- 浅谈windows 编程中SendMessage函数的妙用!!!
热门文章
- linux内核设计与实现 中文第三版 pdf_大牛推荐的5本 Linux 经典必读书
- win7 php redis 扩展,Windows中安装Redis及php redis扩展
- JDK 8 新特性 之 Strams简单使用
- zoom 用户被锁定_重新考虑Zoom的用户体验
- web mp4第一帧_Web成帧器就在这里!
- IDEA、 JetBrains、webstorm、 pycharm 破解教程
- java如何获取一个double的小数位数
- MySQL Date 函数
- Oracle数据表中输入引号等特殊字符
- 禁止sethc.exe运行 防止3389的sethc后门