microsoft/teams.net

Public

mirrored from https://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
cg/core-quoted-replies

Branches

Tags

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

Clone

HTTPS

Download ZIP

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

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