-
Notifications
You must be signed in to change notification settings - Fork 726
/
AppIconBadgingInMeeting.cs
245 lines (218 loc) · 11 KB
/
AppIconBadgingInMeeting.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
// <copyright file="AppIconBadgingInMeeting.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
// </copyright>
using AdaptiveCards;
using AdaptiveCards.Templating;
using AppIconBadgingInMeetings.Models;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Teams;
using Microsoft.Bot.Schema;
using Microsoft.Bot.Schema.Teams;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AppIconBadgingInMeetings
{
public class AppIconBadgingInMeeting : TeamsActivityHandler
{
private readonly IConfiguration _config;
public AppIconBadgingInMeeting(IConfiguration configuration)
{
_config = configuration;
}
/// <summary>
/// Invoked when a message activity is recieved in chat.
/// </summary>
/// <param name="turnContext">The context object for this turn.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects
/// or threads to receive notice of cancellation.</param>
/// <returns>A task that represents the work queued to execute.</returns>
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
if (turnContext.Activity.Value == null)
{
turnContext.Activity.RemoveRecipientMention();
if (turnContext.Activity.Text.Trim() == "SendNotification")
{
var meetingPartipantsList = new List<ParticipantDetail>();
// Get the list of members that are part of meeting group.
var participants = await TeamsInfo.GetPagedMembersAsync(turnContext);
var meetingId = turnContext.Activity.TeamsGetMeetingInfo()?.Id ?? throw new InvalidOperationException("This method is only valid within the scope of a MS Teams Meeting.");
foreach (var member in participants.Members)
{
TeamsMeetingParticipant participantDetails = await TeamsInfo.GetMeetingParticipantAsync(turnContext, meetingId, member.AadObjectId, _config["TenandId"]).ConfigureAwait(false);
// Select only those members that present when meeting is started.
if (participantDetails.Meeting.InMeeting == true)
{
var meetingParticipant = new ParticipantDetail() { Id = member.Id, Name = member.GivenName };
meetingPartipantsList.Add(meetingParticipant);
}
}
var meetingNotificationDetails = new MeetingNotification
{
ParticipantDetails = meetingPartipantsList
};
// Send and adaptive card to user to select members for sending targeted notifications.
Attachment adaptiveCardAttachment = GetAdaptiveCardAttachment("SendTargetNotificationCard.json", meetingNotificationDetails);
await turnContext.SendActivityAsync(MessageFactory.Attachment(adaptiveCardAttachment));
}
else
{
await turnContext.SendActivityAsync(MessageFactory.Text("Please type `SendNotification` to send In-meeting notifications."));
}
}
else
{
await HandleActions(turnContext, cancellationToken);
}
}
/// <summary>
/// Method to handle different notification actions in meeting.
/// </summary>
/// <param name="turnContext">The context object for this turn.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects
/// or threads to receive notice of cancellation.</param>
/// <returns>A task that represents the work queued to execute.</returns>
private async Task HandleActions(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
var action = JsonConvert.DeserializeObject<ActionBase>(turnContext.Activity.Value.ToString());
switch (action.Type)
{
case "AppIconBadging":
try
{
var actionSet = JsonConvert.DeserializeObject<ActionBase>(turnContext.Activity.Value.ToString());
var selectedMembers = actionSet.Choice;
var meetingId = turnContext.Activity.TeamsGetMeetingInfo()?.Id ?? throw new InvalidOperationException("This method is only valid within the scope of a MS Teams Meeting.");
TargetedMeetingNotification notification = GetAppIconBadging(selectedMembers.Split(',').ToList());
await TeamsInfo.SendMeetingNotificationAsync(turnContext, notification, meetingId);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
break;
case "SatgeViewNotification":
try
{
var actionSet = JsonConvert.DeserializeObject<ActionBase>(turnContext.Activity.Value.ToString());
var selectedMembers = actionSet.Choice;
var pageUrl = _config["BaseUrl"] + "/hello";
var meetingId = turnContext.Activity.TeamsGetMeetingInfo()?.Id ?? throw new InvalidOperationException("This method is only valid within the scope of a MS Teams Meeting.");
TargetedMeetingNotification notification = GetStageViewNotification(selectedMembers.Split(',').ToList(), pageUrl);
await TeamsInfo.SendMeetingNotificationAsync(turnContext, notification, meetingId);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
break;
default:
break;
}
}
/// <summary>
/// Invoked when new member is added to conversation.
/// </summary>
/// <param name="membersAdded">List of members added to the conversation.</param>
/// <param name="turnContext">The context object for this turn.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects
/// or threads to receive notice of cancellation.</param>
/// <returns>A task that represents the work queued to execute.</returns>
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
var welcomeText = "Hello and welcome to App Icon Badging and Stage View notification! type 'SendNotification' to send in meeting notification";
foreach (var member in membersAdded)
{
if (member.Id != turnContext.Activity.Recipient.Id)
{
await turnContext.SendActivityAsync(MessageFactory.Text(welcomeText, welcomeText), cancellationToken);
}
}
}
/// <summary>
/// Invoked when submit activity is recieved from task module.
/// </summary>
/// <param name="fileName">Name of the file containing adaptive card.</param>
/// <param name="cardData">The data that needs to be binded with the card.</param>
/// or threads to receive notice of cancellation.</param>
/// <returns>A an adaptive card attachment.</returns>
private Attachment GetAdaptiveCardAttachment(string fileName, object cardData)
{
var templateJson = File.ReadAllText("./Cards/" + fileName);
AdaptiveCardTemplate template = new AdaptiveCardTemplate(templateJson);
string cardJson = template.Expand(cardData);
AdaptiveCardParseResult result = AdaptiveCard.FromJson(cardJson);
// Get card from result
AdaptiveCard card = result.Card;
var adaptiveCardAttachment = new Attachment
{
ContentType = AdaptiveCard.ContentType,
Content = card,
};
return adaptiveCardAttachment;
}
/// <summary>
/// Send App Icon Badging Notification to recipients
/// </summary>
/// <param name="recipients">List of members added to the conversation.</param>
/// <returns>Target meeting notification object.</returns>
private TargetedMeetingNotification GetAppIconBadging(List<string> recipients)
{
TargetedMeetingNotification notification = new TargetedMeetingNotification()
{
Type = "TargetedMeetingNotification",
Value = new TargetedMeetingNotificationValue()
{
Recipients = recipients,
Surfaces = new List<Surface>()
{
new MeetingTabIconSurface()
},
}
};
return notification;
}
/// <summary>
/// Send Stage View Notification to recipients
/// </summary>
/// <param name="recipients">List of members added to the conversation.</param>
/// <param name="pageUrl">page url that will be load in the notification.</param>
/// <returns>Target meeting notification object.</returns>
private TargetedMeetingNotification GetStageViewNotification(List<string> recipients, string pageUrl)
{
TargetedMeetingNotification notification = new TargetedMeetingNotification()
{
Type = "TargetedMeetingNotification",
Value = new TargetedMeetingNotificationValue()
{
Recipients = recipients,
Surfaces = new List<Surface>()
{
new MeetingStageSurface<TaskModuleContinueResponse>()
{
ContentType = ContentType.Task,
Content = new TaskModuleContinueResponse
{
Value = new TaskModuleTaskInfo()
{
Title = "Stage View Notification",
Height =300,
Width = 400,
Url = pageUrl
}
}
}
},
}
};
return notification;
}
}
}