microsoft/teams.net

Public

mirrored fromhttps://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
copilot/sub-pr-338

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

core/src/Microsoft.Teams.Bot.Compat/CompatAdapter.cs

112lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using Microsoft.AspNetCore.Http;
5using Microsoft.Bot.Builder;
6using Microsoft.Bot.Builder.Integration.AspNet.Core;
7using Microsoft.Bot.Schema;
8using Microsoft.Extensions.DependencyInjection;
9using Microsoft.Teams.Bot.Apps;
10using Microsoft.Teams.Bot.Core;
11using Microsoft.Teams.Bot.Core.Schema;
12
13
14namespace Microsoft.Teams.Bot.Compat;
15
16/// <summary>
17/// Provides a compatibility adapter for processing bot activities and HTTP requests using legacy middleware and bot
18/// framework interfaces.
19/// </summary>
20/// <remarks>Use this adapter to bridge between legacy bot framework middleware and newer bot application models.
21/// The adapter allows registration of middleware and error handling delegates, and supports processing HTTP requests
22/// and continuing conversations. Thread safety is not guaranteed; instances should not be shared across concurrent
23/// requests.</remarks>
24public class CompatAdapter : CompatBotAdapter, IBotFrameworkHttpAdapter
25{
26 private readonly TeamsBotApplication _teamsBotApplication;
27
28 /// <summary>
29 /// Creates a new instance of the <see cref="CompatAdapter"/> class.
30 /// </summary>
31 /// <param name="sp"></param>
32 public CompatAdapter(IServiceProvider sp) : base(sp)
33 {
34 _teamsBotApplication = sp.GetRequiredService<TeamsBotApplication>();
35 }
36
37 /// <summary>
38 /// Processes an incoming HTTP request and generates an appropriate HTTP response using the provided bot instance.
39 /// </summary>
40 /// <param name="httpRequest">The incoming HTTP request containing the bot activity. Cannot be null.</param>
41 /// <param name="httpResponse">The HTTP response to write results to. Cannot be null.</param>
42 /// <param name="bot">The bot instance that will process the activity. Cannot be null.</param>
43 /// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
44 /// <returns>A task that represents the asynchronous processing operation.</returns>
45 public async Task ProcessAsync(HttpRequest httpRequest, HttpResponse httpResponse, IBot bot, CancellationToken cancellationToken = default)
46 {
47 ArgumentNullException.ThrowIfNull(httpRequest);
48 ArgumentNullException.ThrowIfNull(httpResponse);
49 ArgumentNullException.ThrowIfNull(bot);
50
51 CoreActivity? coreActivity = null;
52 _teamsBotApplication.OnActivity = async (activity, ct) =>
53 {
54 coreActivity = activity;
55 TurnContext turnContext = new(this, activity.ToCompatActivity());
56 turnContext.TurnState.Add<Microsoft.Bot.Connector.Authentication.UserTokenClient>(new CompatUserTokenClient(_teamsBotApplication.UserTokenClient));
57 CompatConnectorClient connectionClient = new(new CompatConversations(_teamsBotApplication.ConversationClient) { ServiceUrl = activity.ServiceUrl?.ToString() });
58 turnContext.TurnState.Add<Microsoft.Bot.Connector.IConnectorClient>(connectionClient);
59 turnContext.TurnState.Add<Microsoft.Teams.Bot.Apps.TeamsApiClient>(_teamsBotApplication.TeamsApiClient);
60 await MiddlewareSet.ReceiveActivityWithStatusAsync(turnContext, bot.OnTurnAsync, ct).ConfigureAwait(false);
61 };
62
63 try
64 {
65 await _teamsBotApplication.ProcessAsync(httpRequest.HttpContext, cancellationToken).ConfigureAwait(false);
66 }
67 catch (Exception ex)
68 {
69 if (OnTurnError != null)
70 {
71 if (ex is BotHandlerException aex)
72 {
73 coreActivity = aex.Activity;
74 using TurnContext turnContext = new(this, coreActivity!.ToCompatActivity());
75 await OnTurnError(turnContext, ex).ConfigureAwait(false);
76 }
77 else
78 {
79 throw;
80 }
81 }
82 else
83 {
84 throw;
85 }
86 }
87 }
88
89 /// <summary>
90 /// Continues an existing bot conversation by invoking the specified callback with the provided conversation
91 /// reference.
92 /// </summary>
93 /// <remarks>Use this method to resume a conversation at a specific point, such as in response to an event
94 /// or proactive message. The callback is executed within the context of the continued conversation.</remarks>
95 /// <param name="botId">The unique identifier of the bot participating in the conversation.</param>
96 /// <param name="reference">A reference to the conversation to continue. Must not be null.</param>
97 /// <param name="callback">A delegate that handles the bot logic for the continued conversation. The callback receives a turn context and
98 /// cancellation token.</param>
99 /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
100 /// <returns>A task that represents the asynchronous operation.</returns>
101 public async override Task ContinueConversationAsync(string botId, ConversationReference reference, BotCallbackHandler callback, CancellationToken cancellationToken)
102 {
103 ArgumentNullException.ThrowIfNull(reference);
104 ArgumentNullException.ThrowIfNull(callback);
105
106 using TurnContext turnContext = new(this, reference.GetContinuationActivity());
107 turnContext.TurnState.Add<Microsoft.Bot.Connector.Authentication.UserTokenClient>(new CompatUserTokenClient(_teamsBotApplication.UserTokenClient));
108 turnContext.TurnState.Add<Microsoft.Bot.Connector.IConnectorClient>(new CompatConnectorClient(new CompatConversations(_teamsBotApplication.ConversationClient) { ServiceUrl = reference.ServiceUrl }));
109 turnContext.TurnState.Add<Microsoft.Teams.Bot.Apps.TeamsApiClient>(_teamsBotApplication.TeamsApiClient);
110 await RunPipelineAsync(turnContext, callback, cancellationToken).ConfigureAwait(false);
111 }
112}
113