forked from microsoft/CopilotStudioSamples
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRelayBot.cs
More file actions
99 lines (86 loc) · 4.9 KB
/
Copy pathRelayBot.cs
File metadata and controls
99 lines (86 loc) · 4.9 KB
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
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Microsoft.Bot.Builder;
using Microsoft.Bot.Connector.DirectLine;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DirectLineActivity = Microsoft.Bot.Connector.DirectLine.Activity;
using DirectLineActivityTypes = Microsoft.Bot.Connector.DirectLine.ActivityTypes;
using IConversationUpdateActivity = Microsoft.Bot.Schema.IConversationUpdateActivity;
using IMessageActivity = Microsoft.Bot.Schema.IMessageActivity;
namespace Microsoft.PowerVirtualAgents.Samples.RelayBotSample.Bots
{
/// <summary>
/// This IBot implementation shows how to connect
/// an external Azure Bot Service channel bot (external bot)
/// to your Power Virtual Agent bot
/// </summary>
public class RelayBot : ActivityHandler
{
private const int WaitForBotResponseMaxMilSec = 5 * 1000;
private const int PollForBotResponseIntervalMilSec = 1000;
private static ConversationManager s_conversationManager = ConversationManager.Instance;
private ResponseConverter _responseConverter;
private IBotService _botService;
public RelayBot(IBotService botService, ConversationManager conversationManager)
{
_botService = botService;
_responseConverter = new ResponseConverter();
}
// Invoked when a conversation update activity is received from the external Azure Bot Service channel
// Start a Power Virtual Agents bot conversation and store the mapping
protected override async Task OnConversationUpdateActivityAsync(ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
await s_conversationManager.GetOrCreateBotConversationAsync(turnContext.Activity.Conversation.Id, _botService);
}
// Invoked when a message activity is received from the user
// Send the user message to Power Virtual Agent bot and get response
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
var currentConversation = await s_conversationManager.GetOrCreateBotConversationAsync(turnContext.Activity.Conversation.Id, _botService);
using (DirectLineClient client = new DirectLineClient(currentConversation.Token))
{
// Send user message using directlineClient
await client.Conversations.PostActivityAsync(currentConversation.ConversationtId, new DirectLineActivity()
{
Type = DirectLineActivityTypes.Message,
From = new ChannelAccount { Id = turnContext.Activity.From.Id, Name = turnContext.Activity.From.Name },
Text = turnContext.Activity.Text,
TextFormat = turnContext.Activity.TextFormat,
Locale = turnContext.Activity.Locale,
});
await RespondPowerVirtualAgentsBotReplyAsync(client, currentConversation, turnContext);
}
// Update LastConversationUpdateTime for session management
currentConversation.LastConversationUpdateTime = DateTime.Now;
}
private async Task RespondPowerVirtualAgentsBotReplyAsync(DirectLineClient client, RelayConversation currentConversation, ITurnContext<IMessageActivity> turnContext)
{
var retryMax = WaitForBotResponseMaxMilSec / PollForBotResponseIntervalMilSec;
for (int retry = 0; retry < retryMax; retry++)
{
// Get bot response using directlineClient,
// response contains whole conversation history including user & bot's message
ActivitySet response = await client.Conversations.GetActivitiesAsync(currentConversation.ConversationtId, currentConversation.WaterMark);
// Filter bot's reply message from response
List<DirectLineActivity> botResponses = response?.Activities?.Where(x =>
x.Type == DirectLineActivityTypes.Message &&
string.Equals(x.From.Name, _botService.GetBotName(), StringComparison.Ordinal)).ToList();
if (botResponses?.Count() > 0)
{
if (int.Parse(response?.Watermark ?? "0") <= int.Parse(currentConversation.WaterMark ?? "0"))
{
// means user sends new message, should break previous response poll
return;
}
currentConversation.WaterMark = response.Watermark;
await turnContext.SendActivitiesAsync(_responseConverter.ConvertToBotSchemaActivities(botResponses).ToArray());
}
Thread.Sleep(PollForBotResponseIntervalMilSec);
}
}
}
}