forked from microsoft/BotBuilder-Samples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SimplePromptBot.cs
131 lines (119 loc) · 6.58 KB
/
SimplePromptBot.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
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Schema;
namespace Microsoft.BotBuilderSamples
{
/// <summary>
/// Represents a bot that processes incoming activities.
/// For each user interaction, an instance of this class is created and the OnTurnAsync method is called.
/// This is a Transient lifetime service. Transient lifetime services are created
/// each time they're requested. For each Activity received, a new instance of this
/// class is created. Objects that are expensive to construct, or have a lifetime
/// beyond the single turn, should be carefully managed.
/// For example, the <see cref="MemoryStorage"/> object and associated
/// <see cref="IStatePropertyAccessor{T}"/> object are created with a singleton lifetime.
/// </summary>
/// <seealso cref="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1"/>
public class SimplePromptBot : IBot
{
private const string WelcomeText = "Welcome to Simple Prompt Bot. This bot will introduce you to prompts. Type anything to get started.";
private readonly SimplePromptBotAccessors _accessors;
/// <summary>
/// The <see cref="DialogSet"/> that contains all the Dialogs that can be used at runtime.
/// </summary>
private readonly DialogSet _dialogs;
/// <summary>
/// Initializes a new instance of the <see cref="SimplePromptBot"/> class.
/// </summary>
/// <param name="accessors">The state accessors this instance will be needing at runtime.</param>
public SimplePromptBot(SimplePromptBotAccessors accessors)
{
_accessors = accessors ?? throw new ArgumentNullException(nameof(accessors));
_dialogs = new DialogSet(accessors.ConversationDialogState);
_dialogs.Add(new TextPrompt("name"));
}
/// <summary>
/// This controls what happens when an <see cref="Activity"/> gets sent to the bot.
/// </summary>
/// <param name="turnContext">Provides the <see cref="ITurnContext"/> for the turn of the bot.</param>
/// <param name="cancellationToken" >(Optional) A <see cref="CancellationToken"/> that can be used by other objects
/// or threads to receive notice of cancellation.</param>
/// <returns>A <see cref="Task"/> that represents the work queued to execute.</returns>
public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
if (turnContext == null)
{
throw new ArgumentNullException(nameof(turnContext));
}
// Handle Message activity type, which is the main activity type for shown within a conversational interface
// Message activities may contain text, speech, interactive cards, and binary or unknown attachments.
// see https://aka.ms/about-bot-activity-message to learn more about the message and other activity types
if (turnContext.Activity.Type == ActivityTypes.Message)
{
// Run the DialogSet - let the framework identify the current state of the dialog from
// the dialog stack and figure out what (if any) is the active dialog.
var dialogContext = await _dialogs.CreateContextAsync(turnContext, cancellationToken);
var results = await dialogContext.ContinueDialogAsync(cancellationToken);
// If the DialogTurnStatus is Empty we should start a new dialog.
if (results.Status == DialogTurnStatus.Empty)
{
// A prompt dialog can be started directly on the DialogContext. The prompt text is given in the PromptOptions.
await dialogContext.PromptAsync(
"name",
new PromptOptions { Prompt = MessageFactory.Text("Please enter your name.") },
cancellationToken);
}
// We had a dialog run (it was the prompt). Now it is Complete.
else if (results.Status == DialogTurnStatus.Complete)
{
// Check for a result.
if (results.Result != null)
{
// Finish by sending a message to the user. Next time ContinueAsync is called it will return DialogTurnStatus.Empty.
await turnContext.SendActivityAsync(MessageFactory.Text($"Thank you, I have your name as '{results.Result}'."));
}
}
}
// Processes ConversationUpdate Activities to welcome the user.
else if (turnContext.Activity.Type == ActivityTypes.ConversationUpdate)
{
if (turnContext.Activity.MembersAdded.Any())
{
await SendWelcomeMessageAsync(turnContext, cancellationToken);
}
}
else
{
await turnContext.SendActivityAsync($"{turnContext.Activity.Type} event detected", cancellationToken: cancellationToken);
}
// Save the new turn count into the conversation state.
await _accessors.ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
}
/// <summary>
/// Sends a welcome message to the user.
/// </summary>
/// <param name="turnContext">A <see cref="ITurnContext"/> containing all the data needed
/// for processing this conversation turn. </param>
/// <param name="cancellationToken">(Optional) A <see cref="CancellationToken"/> that can be used by other objects
/// or threads to receive notice of cancellation.</param>
/// <returns>A <see cref="Task"/> that represents the work queued to execute.</returns>
private static async Task SendWelcomeMessageAsync(ITurnContext turnContext, CancellationToken cancellationToken)
{
foreach (var member in turnContext.Activity.MembersAdded)
{
if (member.Id != turnContext.Activity.Recipient.Id)
{
var reply = turnContext.Activity.CreateReply();
reply.Text = WelcomeText;
await turnContext.SendActivityAsync(reply, cancellationToken);
}
}
}
}
}