Skip to the content.

Teams Meeting 实时事件通知

Microsoft Teams最近推出了很多新的功能和api,我们今天就来一起看一下 teams 会议的实时事件通知,我觉得有了这个功能,我们的app,我们的bot又可以有很多可以实现的场景了。

我们来看看如何在 c# 里处理会议开始和结束这两个事件。

protected override async Task OnTeamsMeetingStartAsync(MeetingStartEventDetails startDetails, ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken)
{
    ...
}

protected override async Task OnTeamsMeetingEndAsync(MeetingEndEventDetails endDetails, ITurnContext<IEventActivity> turnContext, CancellationToken cancellationToken)
{
    ...
}

在我们的bot 处理class的地方,我们需要重载 OnTeamsMeetingStartAsyncOnTeamsMeetingEndAsync 就可以了。

这两个函数的第一个参数里含有了事件的具体信息。具体如下:

public partial class MeetingStartEventDetails : MeetingEventDetails
{
    public DateTime StartTime { get; set; }
}

public partial class MeetingEndEventDetails : MeetingEventDetails
{
    public DateTime EndTime { get; set; }
}

public partial class MeetingEventDetails : MeetingDetailsBase
{
    public string MeetingType { get; set; }
}

public partial class MeetingDetailsBase
{
    public string Id { get; set; }
    public Uri JoinUrl { get; set; }
    public string Title { get; set; }
}

上面是我从 teams sdk 源代码里简化出来的代码。大家如果有兴趣,可以查看这里:https://github.com/microsoft/botbuilder-dotnet/tree/main/libraries/Microsoft.Bot.Schema/Teams

从上面的结构里可以看到开始会议的事件里会包含 start time, meeting id, meeting type,join url, title,等信息。类似的结束会议的事件里包含了 end time。

看到这里,可能一些经常看我文章的同学会问,如果不用微软官方的 teams sdk,自己来处理,是否可行,答案是肯定的。通过 ngrok,我们就可以发现 teams 调用我们 bot 的请求的 payload。对于一个开始会议的事件,我简化后的payload 如下:

{ 
    "name": "application/vnd.microsoft.meetingStart", 
    "type": "event", 
    "timestamp": "2021-04-29T16:10:41.1252256Z", 
    // ...
    "channelData": {
        "meeting": {
            "id": "<会议的id>"
        }
        // ...
    },
    "value": {
        "MeetingType": "Scheduled",
        "Title": "<你的会议标题>",
        "Id": "<会议的id>",
        "JoinUrl": "<会议的 url>",
        "StartTime": "2021-04-29T16:17:17.4388966Z"
    },
    "locale": "en-US"
}

特别需要注意的是最前面的那个 name,表明了整个payload是一个 meetingStart 的格式。同样,会议结束的 payload 如下:

{ 
    "name": "application/vnd.microsoft.meetingEnd", 
    "type": "event", 
    "timestamp": "2021-04-29T16:10:41.1252256Z", 
    // ...
    "channelData": {
        "meeting": {
            "id": "<会议的id>"
        }
        // ...
    },
    "value": {
        "MeetingType": "Scheduled",
        "Title": "<你的会议标题>",
        "Id": "<会议的id>",
        "JoinUrl": "<会议的 url>",
        "EndTime": "2021-04-29T16:17:17.4388966Z"
    },
    "locale": "en-US"
}

差别主要在与第一行的 name,和最后那个结构里的 EndTime。看到这里大家是否已经知道如何接受这两个事件了?

最后,我们代码完成后,我们还需要更新一下app的manifest.json。确保我们的app有足够的权限来处理。使用我们最喜欢的编辑器打开 manifest 文件,加入如下的配置。

"webApplicationInfo": {
    "id": "你的 bot id",
    "resource": "https://RscPermission",
},
"authorization": {
    "permissions": {
        "resourceSpecific": [
            {
                "name": "OnlineMeeting.ReadBasic.Chat",
                "type": "Application"
            }
        ]    
    }
}

如果你当前的bot使用较老版本的manifest格式,可以用如下的manifest

"webApplicationInfo": {
    "id": "你的 bot id",
    "resource": "https://RscPermission",
    "applicationPermissions": [
        "OnlineMeeting.ReadBasic.Chat"
    ]
}

可以看到最最关键的是我们的app需要有 OnlineMeeting.ReadBasic.Chat 这个权限。

代码和配置都准备好后,就可以开始调试运行了。

Written on February 5, 2022