microsoft/teams.net

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
next/core

Branches

Tags

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

Clone

HTTPS

Download ZIP

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

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