处理 Microsoft Teams 中的机器人事件
重要
本文基于 v3 Bot Framework SDK。 如果要查找 SDK 的当前文档 4.6 或更高版本,请参阅 对话机器人 部分。
对于在机器人活动范围内发生的事件,Microsoft Teams 会向机器人发送通知。 以下列表提供了用于触发服务逻辑的事件:
- 在将机器人添加到团队时,触发欢迎消息。
- 将机器人添加到群组聊天时,查询并缓存组群组信息。
- 更新关于团队成员身份或频道信息的缓存信息。
- 如果删除了机器人,则删除团队的缓存信息。
- 用户对机器人消息点赞时。
每个机器人事件都作为 Activity
对象发送,其中 messageType
定义对象中的信息。 有关类型 message
的消息,请参阅 发送和接收消息 。
从 conversationUpdate
类型触发的 Teams 和组事件具有作为 对象的一部分传递的 channelData
更多 Teams 事件信息,因此事件处理程序必须查询 channelData
Teams eventType
的有效负载和更多特定于事件的元数据。
下表列出了机器人可以接收并采取措施的事件。
类型 | 有效负载对象 | Teams eventType | 说明 | 范围 |
---|---|---|---|---|
conversationUpdate |
membersAdded |
teamMemberAdded |
添加到团队的成员 | 全部 |
conversationUpdate |
membersRemoved |
teamMemberRemoved |
成员已从团队中删除 |
groupChat & team |
conversationUpdate |
teamRenamed |
已重命名团队 | team |
|
conversationUpdate |
channelCreated |
已创建频道 | team |
|
conversationUpdate |
channelRenamed |
已重命名频道 | team |
|
conversationUpdate |
channelDeleted |
已删除频道 | team |
|
messageReaction |
reactionsAdded |
对机器人消息的回应 | 全部 | |
messageReaction |
reactionsRemoved |
从机器人消息中删除的回应 | 全部 |
添加团队成员或机器人
当机器人收到关于其所属团队的成员身份更新信息时,conversationUpdate
事件就会发送到机器人。 在首次专门为个人对话添加机器人时,机器人也会收到更新。 () 的用户信息 Id
对于机器人是唯一的,可以缓存以供服务将来使用,例如向特定用户发送消息。
添加到团队的机器人或用户
将机器人添加到团队或将新用户添加到已添加机器人的团队时,会发送有效负载中包含 membersAdded
对象的 conversationUpdate
事件。 Teams 还会在 eventType.teamMemberAdded
对象中添加 channelData
。
由于此事件在这两种情况下都发送,因此应解析 membersAdded
对象以确定添加的对象是用户还是机器人本身。 对于后者,最佳做法是向频道发送 欢迎消息 ,以便用户可以了解机器人提供的功能。
示例代码:检查机器人是否是添加的成员
.NET
for (int i = 0; i < sourceMessage.MembersAdded.Count; i++)
{
if (sourceMessage.MembersAdded[i].Id == sourceMessage.Recipient.Id)
{
addedBot = true;
break;
}
}
Node.js
const builder = require('botbuilder');
var c = new builder.ChatConnector({appId: BOT_APP_ID, appPassword: .BOT_SECRET});
var bot = new builder.UniversalBot(c);
bot.on('conversationUpdate', (msg) => {
var members = msg.membersAdded;
// Loop through all members that were just added to the team
for (var i = 0; i < members.length; i++) {
// See if the member added was our bot
if (members[i].id.includes(BOT_APP_ID)) {
var botmessage = new builder.Message()
.address(msg.address)
.text('Hello World!');
bot.send(botmessage, function(err) {});
}
}
});
架构示例:添加到团队的机器人
{
"membersAdded":[
{
"id":"28:f5d48856-5b42-41a0-8c3a-c5f944b679b0"
}
],
"type":"conversationUpdate",
"timestamp":"2017-02-23T19:38:35.312Z",
"localTimestamp":"2017-02-23T12:38:35.312-07:00",
"id":"f:5f85c2ad",
"channelId":"msteams",
"serviceUrl":"https://smba.trafficmanager.net/amer-client-ss.msg/",
"from":{
"id":"29:1I9Is_Sx0OIy2rQ7Xz1lcaPKlO9eqmBRTBuW6XzkFtcjqxTjPaCMij8BVMdBcL9L_RwWNJyAHFQb0TRzXgyQvA"
},
"conversation":{
"isGroup":true,
"conversationType":"channel",
"id":"19:efa9296d959346209fea44151c742e73@thread.skype"
},
"recipient":{
"id":"28:f5d48856-5b42-41a0-8c3a-c5f944b679b0",
"name":"SongsuggesterBot"
},
"channelData":{
"team":{
"id":"19:efa9296d959346209fea44151c742e73@thread.skype"
},
"eventType":"teamMemberAdded",
"tenant":{
"id":"72f988bf-86f1-41af-91ab-2d7cd011db47"
}
}
}
添加到会议的用户
将用户添加到私人预定会议时,将发送有效负载中包含 membersAdded
对象的 conversationUpdate
事件。 即使匿名用户加入会议,也会发送事件详细信息。
注意
- 将匿名用户添加到会议时,membersAdded 有效负载对象没有
aadObjectId
字段。 - 将匿名用户添加到会议时,即使该匿名用户是由其他演示者添加的,有效负载中的
from
对象始终具有会议组织者的 ID。
架构示例:添加到会议中的用户
{
"membersAdded":[
{
"id":"229:1Z_XHWBMhDuehhDBYoPQD6Y1DSFsTtqOZx-SA5Jh9Y4zHKm4VbFGRn7-rK7SWiW1JECwxkMdrWpHoBut2sSyQPA"
}
],
"type":"conversationUpdate",
"timestamp":"2017-02-23T19:38:35.312Z",
"localTimestamp":"2020-09-29T21:11:38.6542339Z",
"id":"f:a8cd1b51-9ddb-bd35-624b-7f7474165df8",
"channelId":"msteams",
"serviceUrl":"https://canary.botapi.skype.com/amer/",
"from":{
"id":"29:1siKxZhSoTapsXvI0gyf7Gywm_HM-4kEQW4BJnWuFYVIVu87xCNP99nidgQRCcwD3L3p_schiMShzx8IDRzf8mw",
"aadObjectId":"f30ba569-abef-4e97-8762-35f85cbae706"
},
"conversation":{
"isGroup":true,
"tenantId":"e15762ef-a8d8-416b-871c-25516354f1fe",
"id":"19:meeting_MWJlNGViOTgtMGExYi00NDA3LWExODgtOTZhMWNlYjM4ZTRj@thread.v2"
},
"recipient":{
"id":"28:3af3604a-d4fc-486b-911e-86fab41aa91c",
"name":"EchoBot1_Rename"
},
"channelData":{
"tenant":{
"id":"e15762ef-a8d8-416b-871c-25516354f1fe"
},
"source":null,
"meeting":{
"id":"MCMxOTptZWV0aW5nX01XSmxOR1ZpT1RndE1HRXhZaTAwTkRBM0xXRXhPRGd0T1RaaE1XTmxZak00WlRSakB0aHJlYWQudjIjMA=="
}
}
}
仅针对个人上下文添加的机器人
当用户直接添加它进行个人聊天时,机器人会收到具备 membersAdded
的 conversationUpdate
。 在这种情况下,机器人收到的有效负载不包含 channelData.team
对象。 如果希望机器人根据范围提供不同的 欢迎消息 ,则应使用此选项作为筛选器。
注意
对于个人范围的机器人,机器人将多次接收 conversationUpdate
事件,即使删除并重新添加机器人也是如此。 对于开发和测试,你可能会发现添加帮助程序函数非常有用,该函数让你可以完全重置机器人。 有关详细信息,请参阅 Node.js 示例 或 C# 示例 ,详细了解如何实现此功能。
架构示例:添加到个人上下文中的机器人
{
"membersAdded": [{
"id": "28:f5d48856-5b42-41a0-8c3a-c5f944b679b0"
},
{
"id": "29:<userID>",
"aadObjectId": "***"
}
],
"type": "conversationUpdate",
"timestamp": "2019-04-23T10:17:44.349Z",
"id": "f:5f85c2ad",
"channelId": "msteams",
"serviceUrl": "https://smba.trafficmanager.net/amer-client-ss.msg/",
"from": {
"id": "29:<USERID>",
"aadObjectId": "***"
},
"conversation": {
"conversationType": "personal",
"id": "***"
},
"recipient": {
"id": "28:<BOT ID>",
"name": "<BOT NAME>"
},
"channelData": {
"tenant": {
"id": "<TENANT ID>"
}
}
}
已删除团队成员或机器人
从团队中删除机器人、或者从添加了机器人的团队中删除用户时,将发送有效负载中具有 membersRemoved
对象的 conversationUpdate
事件。 Teams 还会在 eventType.teamMemberRemoved
对象中添加 channelData
。 与 membersAdded
对象一样,应解析机器人应用 ID 的 membersRemoved
对象,以确定被删除的对象。
架构示例:被删除的团队成员
{
"membersRemoved": [
{
"id": "29:1_LCi5Up14pAy65yZuaJzG1uIT7ujYhjjSTsUNqjORsZHjLHKiQIBJa4cX2XsAsRoaY7va2w6ZymA9-1VtSY_g"
}
],
"type": "conversationUpdate",
"timestamp": "2017-02-23T19:37:06.96Z",
"localTimestamp": "2017-02-23T12:37:06.96-07:00",
"id": "f:d8a6a4aa",
"channelId": "msteams",
"serviceUrl": "https://smba.trafficmanager.net/amer-client-ss.msg/",
"from": {
"id": "29:1I9Is_Sx0OIy2rQ7Xz1lcaPKlO9eqmBRTBuW6XzkFtcjqxTjPaCMij8BVMdBcL9L_RwWNJyAHFQb0TRzXgyQvA"
},
"conversation": {
"isGroup": true,
"conversationType": "channel",
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"recipient":
{
"id": "28:f5d48856-5b42-41a0-8c3a-c5f944b679b0",
"name": "SongsuggesterBot"
},
"channelData": {
"team": {
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"eventType": "teamMemberRemoved",
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}
}
}
从会议中删除的用户
当用户从私人预定会议中删除时,将发送有效负载中包含 membersRemoved
对象的 conversationUpdate
事件。 即使匿名用户加入会议,也会发送事件详细信息。
注意
- 从会议中删除匿名用户时,membersRemoved 有效负载对象没有
aadObjectId
字段。 - 从会议中删除匿名用户时,即使该匿名用户是由其他演示者删除的,有效负载中的
from
对象始终具有会议组织者的 ID。
架构示例:从会议中删除的用户
{
"membersRemoved":
{
"id": "29:1Z_XHWBMhDuehhDBYoPQD6Y1DSFsTtqOZx-SA5Jh9Y4zHKm4VbFGRn7-rK7SWiW1JECwxkMdrWpHoBut2sSyQPA"
}
],
"type": "conversationUpdate",
"timestamp": "2020-09-29T21:15:08.6391139Z",
"id": "f:ee8dfdf3-54ac-51de-05da-9d49514974bb",
"channelId": "msteams",
"serviceUrl": "https://canary.botapi.skype.com/amer/",
"from": {
"id": "29:1siKxZhSoTapsXvI0gyf7Gywm_HM-4kEQW4BJnWuFYVIVu87xCNP99nidgQRCcwD3L3p_schiMShzx8IDRzf8mw",
"aadObjectId": "f30ba569-abef-4e97-8762-35f85cbae706"
},
"conversation": {
"isGroup": true,
"tenantId": "e15762ef-a8d8-416b-871c-25516354f1fe",
"id": "19:meeting_MWJlNGViOTgtMGExYi00NDA3LWExODgtOTZhMWNlYjM4ZTRj@thread.v2"
},
"recipient": {
"id": "28:3af3604a-d4fc-486b-911e-86fab41aa91c",
"name": "EchoBot1_Rename"
},
"channelData": {
"tenant": {
"id": "e15762ef-a8d8-416b-871c-25516354f1fe"
},
"source": null,
"meeting": {
"id": "MCMxOTptZWV0aW5nX01XSmxOR1ZpT1RndE1HRXhZaTAwTkRBM0xXRXhPRGd0T1RaaE1XTmxZak00WlRSakB0aHJlYWQudjIjMA=="
}
}
}
团队名称更新
注意
没有查询所有团队名称的功能,并且没有从其他事件的有效负载中返回团队名称。
当机器人所在的团队已重命名时,机器人会收到通知。 它在 channelData
对象中接收具备 eventType.teamRenamed
的 conversationUpdate
事件。 没有有关创建或删除团队的通知,因为机器人仅作为团队的一部分存在,并且不会在添加机器人的范围之外获得可见性。
架构示例:已重命名团队
{
"type": "conversationUpdate",
"timestamp": "2017-02-23T19:35:56.825Z",
"localTimestamp": "2017-02-23T12:35:56.825-07:00",
"id": "f:1406033e",
"channelId": "msteams",
"serviceUrl": "https://smba.trafficmanager.net/amer-client-ss.msg/",
"from": {
"id": "29:1I9Is_Sx0O-Iy2rQ7Xz1lcaPKlO9eqmBRTBuW6XzkFtcjqxTjPaCMij8BVMdBcL9L_RwWNJyAHFQb0TRzXgyQvA"
},
"conversation": {
"isGroup": true,
"conversationType": "channel",
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"recipient": {
"id": "28:f5d48856-5b42-41a0-8c3a-c5f944b679b0",
"name": "SongsuggesterLocal"
},
"channelData": {
"team": {
"id": "19:efa9296d959346209fea44151c742e73@thread.skype",
"name": "New Team Name"
},
"eventType": "teamRenamed",
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}
}
}
频道更新
在添加机器人的团队中创建、重命名或删除频道时,会通知机器人。 同样, conversationUpdate
接收事件,并发送特定于 Teams 的事件标识符作为对象的一部分 channelData.eventType
,其中通道数据的 channel.id
是通道的 GUID,并 channel.name
包含通道名称本身。
频道事件如下所示:
- channelCreated 用户向团队添加新频道。
- channelRenamed 用户重命名现有通道。
- channelDeleted 用户删除频道。
完整架构示例:channelCreated
{
"type": "conversationUpdate",
"timestamp": "2017-02-23T19:34:07.478Z",
"localTimestamp": "2017-02-23T12:34:07.478-07:00",
"id": "f:dd6ec311",
"channelId": "msteams",
"serviceUrl": "https://smba.trafficmanager.net/amer-client-ss.msg/",
"from": {
"id": "29:1wR7IdIRIoerMIWbewMi75JA3scaMuxvFon9eRQW2Nix5loMDo0362st2IaRVRirPZBv1WdXT8TIFWWmlQCizZQ"
},
"conversation": {
"isGroup": true,
"conversationType": "channel",
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"recipient": {
"id": "28:f5d48856-5b42-41a0-8c3a-c5f944b679b0",
"name": "SongsuggesterBot"
},
"channelData": {
"channel": {
"id": "19:6d97d816470f481dbcda38244b98689a@thread.skype",
"name": "FunDiscussions"
},
"team": {
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"eventType": "channelCreated",
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}
}
}
架构摘录:channelRenamed 的 channelData
⋮
"channelData": {
"channel": {
"id": "19:6d97d816470f481dbcda38244b98689a@thread.skype",
"name": "PhotographyUpdates"
},
"team": {
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"eventType": "channelRenamed",
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}
}
⋮
架构摘录:channelDeleted 的 channelData
⋮
"channelData": {
"channel": {
"id": "19:6d97d816470f481dbcda38244b98689a@thread.skype",
"name": "PhotographyUpdates"
},
"team": {
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"eventType": "channelDeleted",
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}
}
⋮
回应
messageReaction
当用户添加或删除对最初由机器人发送的消息的反应时,将发送事件。
replyToId
包含特定消息的 ID。
架构示例:用户点赞了某条消息
{
"reactionsAdded": [
{
"type": "like"
}
],
"type": "messageReaction",
"timestamp": "2017-10-16T18:45:41.943Z",
"id": "f:9f78d1f3",
"channelId": "msteams",
"serviceUrl": "https://smba.trafficmanager.net/amer-client-ss.msg/",
"from": {
"id": "29:1I9Is_Sx0O-Iy2rQ7Xz1lcaPKlO9eqmBRTBuW6XzkFtcjqxTjPaCMij8BVMdBcL9L_RwWNJyAHFQb0TRzXgyQvA",
"aadObjectId": "c33aafc4-646d-4543-9d4c-abd28e4d2110"
},
"conversation": {
"isGroup": true,
"conversationType": "channel",
"id": "19:3629591d4b774aa08cb0887902eee7c1@thread.skype"
},
"recipient": {
"id": "28:f5d48856-5b42-41a0-8c3a-c5f944b679b0",
"name": "SongsuggesterLocal"
},
"channelData": {
"channel": {
"id": "19:3629591d4b774aa08cb0887902eee7c1@thread.skype"
},
"team": {
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}
},
"replyToId": "1575667808184"
}
架构示例:用户与消息不同
{
"reactionsRemoved": [
{
"type": "like"
}
],
"type": "messageReaction",
"timestamp": "2017-10-16T18:45:41.943Z",
"id": "f:9f78d1f3",
"channelId": "msteams",
"serviceUrl": "https://smba.trafficmanager.net/amer-client-ss.msg/",
"from": {
"id": "29:1I9Is_Sx0O-Iy2rQ7Xz1lcaPKlO9eqmBRTBuW6XzkFtcjqxTjPaCMij8BVMdBcL9L_RwWNJyAHFQb0TRzXgyQvA",
"aadObjectId": "c33aafc4-646d-4543-9d4c-abd28e4d2110"
},
"conversation": {
"isGroup": true,
"conversationType": "channel",
"id": "19:3629591d4b774aa08cb0887902eee7c1@thread.skype"
},
"recipient": {
"id": "28:f5d48856-5b42-41a0-8c3a-c5f944b679b0",
"name": "SongsuggesterLocal"
},
"channelData": {
"channel": {
"id": "19:3629591d4b774aa08cb0887902eee7c1@thread.skype"
},
"team": {
"id": "19:efa9296d959346209fea44151c742e73@thread.skype"
},
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}
},
"replyToId": "1575667808184"
}