This repository has been archived by the owner on Jul 2, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 105
/
RootDialog.cs
331 lines (278 loc) · 13 KB
/
RootDialog.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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
namespace AzureBot.Dialogs
{
using AuthBot;
using AuthBot.Dialogs;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Dialogs.Internals;
using Microsoft.Bot.Builder.FormFlow;
using Microsoft.Bot.Builder.Luis;
using Microsoft.Bot.Builder.Luis.Models;
using Microsoft.Bot.Connector;
using System;
using System.Configuration;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
[LuisModel("d2129bee-5d15-4c78-be3b-2005e3c08cd4", "110c81d75bdb4f918a991696cd09f66b")]
[Serializable]
public class RootDialog : AzureBotLuisDialog<string>
{
private static Lazy<string> resourceId = new Lazy<string>(() => ConfigurationManager.AppSettings["ActiveDirectory.ResourceId"]);
private bool serviceUrlSet = false;
private string userToBot;
[LuisIntent("")]
[LuisIntent("None")]
public async Task None(IDialogContext context, LuisResult result)
{
var factory = new DialogFactory();
AzureBotLuisDialog<string> dialog = await factory.Create(result.Query);
if (dialog != null)
{
var message = context.MakeMessage();
message.Text = userToBot;
var accessToken = await context.GetAccessToken(resourceId.Value);
if (string.IsNullOrEmpty(accessToken))
{
return;
}
await context.Forward(dialog, this.ResumeAfterForward, message, CancellationToken.None);
}
else
{
if (new[] { "cancel", "reset", "restart", "kill", "undo", "start over" }.Any(c => result.Query.Contains(c)))
{
context.Reset();
context.ConversationData.Clear();
context.UserData.Clear();
context.PrivateConversationData.Clear();
await context.FlushAsync(CancellationToken.None);
await context.PostAsync($"Alright, I've reset everything, let's try again.");
await this.Help(context, new LuisResult());
}
else
{
string message = $"Sorry, I did not understand '{result.Query}'. Type 'help' if you need assistance.";
await context.PostAsync(message);
context.Wait(MessageReceived);
}
}
}
[LuisIntent("Help")]
public async Task Help(IDialogContext context, LuisResult result)
{
string message = "";
var accessToken = await context.GetAccessToken(resourceId.Value);
if (string.IsNullOrEmpty(accessToken))
{
message += $"Hello!\n\n";
}
message += "I can help you: \n";
message += $"* List, Switch and Select an Azure subscription\n";
message += $"* List, Start, Shutdown (power off your VM, still incurring compute charges), and Stop (deallocates your VM, no charges) your virtual machines\n";
message += $"* List your automation accounts and your runbooks\n";
message += $"* Start a runbook, get the description of a runbook, get the status and output of automation jobs\n";
message += $"* Login and Logout of an Azure Subscription\n\n";
if (string.IsNullOrEmpty(accessToken))
{
message += $"By using me, you agree to the Microsoft Privacy Statement and Microsoft Services Agreement on http://aka.ms/AzureBot \n\n";
message += $"Please type **login** to interact with me for the first time.";
}
await context.PostAsync(message);
context.Wait(this.MessageReceived);
}
protected override async Task MessageReceived(IDialogContext context, IAwaitable<IMessageActivity> item)
{
var message = await item;
//No way to get the message in the LuisIntent methods so saving it here
userToBot = message.Text.ToLowerInvariant();
if (!serviceUrlSet)
{
context.PrivateConversationData.SetValue("ServiceUrl", message.ServiceUrl);
serviceUrlSet = true;
}
if (userToBot.Contains("help") || message.Type != ActivityTypes.Message)
{
await base.MessageReceived(context, item);
return;
}
var accessToken = await context.GetAccessToken(resourceId.Value);
if (string.IsNullOrEmpty(accessToken))
{
if (userToBot.Contains("login"))
{
await context.Forward(new AzureAuthDialog(resourceId.Value), this.ResumeAfterAuth, message, CancellationToken.None);
}
else
{
await this.Help(context, new LuisResult());
}
}
else
{
if (string.IsNullOrEmpty(context.GetSubscriptionId()))
{
await this.UseSubscriptionAsync(context, new LuisResult());
}
else
{
await base.MessageReceived(context, item);
}
}
}
[LuisIntent("ListSubscriptions")]
public async Task ListSubscriptionsAsync(IDialogContext context, LuisResult result)
{
var accessToken = await context.GetAccessToken(resourceId.Value);
if (string.IsNullOrEmpty(accessToken))
{
return;
}
var subscriptions = await Domain.Subscription.ListSubscriptionsAsync(accessToken);
int index = 0;
var subscriptionsText = subscriptions.Aggregate(
string.Empty,
(current, next) =>
{
index++;
return current += $"\r\n{index}. {next.DisplayName}";
});
await context.PostAsync($"Your subscriptions are: {subscriptionsText}");
context.Wait(MessageReceived);
}
[LuisIntent("CurrentSubscription")]
public async Task GetCurrentSubscriptionAsync(IDialogContext context, LuisResult result)
{
var accessToken = await context.GetAccessToken(resourceId.Value);
if (string.IsNullOrEmpty(accessToken))
{
return;
}
var subscriptionId = context.GetSubscriptionId();
var currentSubscription = await Domain.Subscription.GetSubscription(accessToken, subscriptionId);
await context.PostAsync($"Your current subscription is '{currentSubscription.DisplayName}'.");
context.Wait(MessageReceived);
}
[LuisIntent("UseSubscription")]
public async Task UseSubscriptionAsync(IDialogContext context, LuisResult result)
{
EntityRecommendation subscriptionEntity;
var accessToken = await context.GetAccessToken(resourceId.Value);
if (string.IsNullOrEmpty(accessToken))
{
context.Wait(MessageReceived);
return;
}
var availableSubscriptions = await Domain.Subscription.ListSubscriptionsAsync(accessToken);
// check if the user specified a subscription name in the command
if (result.TryFindEntity("Subscription", out subscriptionEntity))
{
// obtain the name specified by the user - text in LUIS result is different
var subscriptionName = subscriptionEntity.GetEntityOriginalText(result.Query);
// ensure that the subscription exists
var selectedSubscription = availableSubscriptions.FirstOrDefault(p => p.DisplayName.Equals(subscriptionName, StringComparison.InvariantCultureIgnoreCase));
if (selectedSubscription == null)
{
await context.PostAsync($"The '{subscriptionName}' subscription was not found.");
context.Wait(this.MessageReceived);
return;
}
subscriptionEntity.Entity = selectedSubscription.DisplayName;
subscriptionEntity.Type = "SubscriptionId";
}
var formState = new Forms.SubscriptionFormState(availableSubscriptions);
if (availableSubscriptions.Count() == 1)
{
formState.SubscriptionId = availableSubscriptions.Single().SubscriptionId;
formState.DisplayName = availableSubscriptions.Single().DisplayName;
}
var form = new FormDialog<Forms.SubscriptionFormState>(
formState,
Forms.EntityForms.BuildSubscriptionForm,
FormOptions.PromptInStart,
result.Entities);
context.Call(form, this.UseSubscriptionFormComplete);
}
[LuisIntent("Logout")]
public async Task Logout(IDialogContext context, LuisResult result)
{
context.Cleanup();
await context.Logout();
context.Wait(this.MessageReceived);
}
//[LuisIntent("DetermineResource")]
//public async Task DetermineResourceAsync(IDialogContext context, LuisResult result)
//{
// var accessToken = await context.GetAccessToken(resourceId.Value);
// if (string.IsNullOrEmpty(accessToken))
// {
// return;
// }
// var factory = new DialogFactory();
// var message = context.MakeMessage();
// message.Text = userToBot;
// var dialog = factory.Create(result.Query);
// await context.Forward(dialog, this.ResumeAfterForward, message, CancellationToken.None);
//}
private async Task ResumeAfterForward(IDialogContext context, IAwaitable<string> result)
{
var message = await result;
if (string.IsNullOrEmpty(message))
context.Wait(this.MessageReceived);
else
await None(context, new LuisResult()); //the second dialog didn't understand the command
}
private async Task ResumeAfterAuth(IDialogContext context, IAwaitable<string> result)
{
var message = await result;
await context.PostAsync(message);
await this.UseSubscriptionAsync(context, new LuisResult());
}
private async Task UseSubscriptionFormComplete(IDialogContext context, IAwaitable<Forms.SubscriptionFormState> result)
{
try
{
var subscriptionFormState = await result;
if (!string.IsNullOrEmpty(subscriptionFormState.SubscriptionId))
{
var selectedSubscription = subscriptionFormState.AvailableSubscriptions.Single(sub => sub.SubscriptionId == subscriptionFormState.SubscriptionId);
context.StoreSubscriptionId(subscriptionFormState.SubscriptionId);
await context.PostAsync($"Setting {selectedSubscription.DisplayName} as the current subscription. What would you like to do next?");
context.Wait(this.MessageReceived);
}
else
{
PromptDialog.Confirm(
context,
this.OnLogoutRequested,
"Oops! You don't have any Azure subscriptions under the account you used to log in. To continue using the bot, log in with a different account. Do you want to log out and start over?",
"Didn't get that!",
promptStyle: PromptStyle.None);
}
}
catch (FormCanceledException<Forms.SubscriptionFormState> e)
{
string reply;
if (e.InnerException == null)
{
reply = "You have canceled the operation. What would you like to do next?";
}
else
{
reply = $"Oops! Something went wrong :(. Technical Details: {e.InnerException.Message}";
}
await context.PostAsync(reply);
context.Wait(this.MessageReceived);
}
}
private async Task OnLogoutRequested(IDialogContext context, IAwaitable<bool> confirmation)
{
var result = await confirmation;
if (result)
{
context.Cleanup();
await context.Logout();
}
context.Wait(this.MessageReceived);
}
}
}