microsoft/teams.net

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
5e595aec73b538083f2def3e2971f2cd7f31ca22

Branches

Tags

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

Clone

HTTPS

Download ZIP

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

126lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using System.Text.Json;
5using Microsoft.AspNetCore.Http;
6using Microsoft.Bot.Builder;
7using Microsoft.Bot.Schema;
8using Microsoft.Extensions.Logging;
9using Microsoft.Teams.Bot.Apps;
10using Microsoft.Teams.Bot.Core;
11using Newtonsoft.Json;
12
13
14namespace Microsoft.Teams.Bot.Compat;
15
16/// <summary>
17/// Provides a Bot Framework adapter that enables compatibility between the Bot Framework SDK and a custom bot
18/// application implementation.
19/// </summary>
20/// <remarks>Use this adapter to bridge Bot Framework turn contexts and activities with a custom bot application.
21/// This class is intended for scenarios where integration with non-standard bot runtimes or legacy systems is
22/// required.</remarks>
23/// <param name="botApplication">The bot application instance used to process and send activities within the adapter.</param>
24/// <param name="httpContextAccessor">The HTTP context accessor used to retrieve the current HTTP context for writing invoke responses.</param>
25/// <param name="logger">The logger instance for recording adapter operations and diagnostics.</param>
26[System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1848:Use the LoggerMessage delegates", Justification = "<Pending>")]
27public class CompatBotAdapter(TeamsBotApplication botApplication, IHttpContextAccessor httpContextAccessor = default!, ILogger<CompatBotAdapter> logger = default!) : BotAdapter
28{
29 private readonly JsonSerializerOptions _writeIndentedJsonOptions = new() { WriteIndented = true };
30
31 /// <summary>
32 /// Deletes an activity from the conversation.
33 /// </summary>
34 /// <param name="turnContext">The turn context containing the activity information. Cannot be null.</param>
35 /// <param name="reference">The conversation reference identifying the activity to delete.</param>
36 /// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
37 /// <returns>A task that represents the asynchronous delete operation.</returns>
38 public override async Task DeleteActivityAsync(ITurnContext turnContext, ConversationReference reference, CancellationToken cancellationToken)
39 {
40 ArgumentNullException.ThrowIfNull(turnContext);
41 await botApplication.ConversationClient.DeleteActivityAsync(turnContext.Activity.FromCompatActivity(), cancellationToken: cancellationToken).ConfigureAwait(false);
42 }
43
44 /// <summary>
45 /// Sends a set of activities to the conversation.
46 /// </summary>
47 /// <param name="turnContext">The turn context for the conversation. Cannot be null.</param>
48 /// <param name="activities">An array of activities to send. Cannot be null.</param>
49 /// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
50 /// <returns>
51 /// A task that represents the asynchronous operation. The task result contains an array of <see cref="ResourceResponse"/>
52 /// objects with the IDs of the sent activities.
53 /// </returns>
54 public override async Task<ResourceResponse[]> SendActivitiesAsync(ITurnContext turnContext, Activity[] activities, CancellationToken cancellationToken)
55 {
56 ArgumentNullException.ThrowIfNull(activities);
57 ArgumentNullException.ThrowIfNull(turnContext);
58
59 ResourceResponse[] responses = new Microsoft.Bot.Schema.ResourceResponse[activities.Length];
60
61 for (int i = 0; i < activities.Length; i++)
62 {
63 Activity activity = activities[i];
64
65 if (activity.Type == ActivityTypes.Trace)
66 {
67 return [new ResourceResponse() { Id = null }];
68 }
69
70 if (activity.Type == "invokeResponse")
71 {
72 WriteInvokeResponseToHttpResponse(activity.Value as InvokeResponse);
73 return [new ResourceResponse() { Id = null }];
74 }
75
76 SendActivityResponse? resp = await botApplication.SendActivityAsync(activity.FromCompatActivity(), cancellationToken).ConfigureAwait(false);
77
78 logger.LogInformation("Resp from SendActivitiesAsync: {RespId}", resp?.Id);
79
80 responses[i] = new Microsoft.Bot.Schema.ResourceResponse() { Id = resp?.Id };
81 }
82 return responses;
83 }
84
85 /// <summary>
86 /// Updates an existing activity in the conversation.
87 /// </summary>
88 /// <param name="turnContext">The turn context for the conversation.</param>
89 /// <param name="activity">The activity with updated content. Cannot be null.</param>
90 /// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
91 /// <returns>
92 /// A task that represents the asynchronous operation. The task result contains a <see cref="ResourceResponse"/>
93 /// with the ID of the updated activity.
94 /// </returns>
95 public override async Task<ResourceResponse> UpdateActivityAsync(ITurnContext turnContext, Activity activity, CancellationToken cancellationToken)
96 {
97 ArgumentNullException.ThrowIfNull(activity);
98 UpdateActivityResponse res = await botApplication.ConversationClient.UpdateActivityAsync(
99 activity.Conversation.Id,
100 activity.Id,
101 activity.FromCompatActivity(),
102 cancellationToken: cancellationToken).ConfigureAwait(false);
103 return new ResourceResponse() { Id = res.Id };
104 }
105
106 private void WriteInvokeResponseToHttpResponse(InvokeResponse? invokeResponse)
107 {
108 ArgumentNullException.ThrowIfNull(invokeResponse);
109 HttpResponse? response = httpContextAccessor?.HttpContext?.Response;
110 if (response is not null && !response.HasStarted)
111 {
112 response.StatusCode = invokeResponse.Status;
113 using StreamWriter httpResponseStreamWriter = new(response.BodyWriter.AsStream());
114 using JsonTextWriter httpResponseJsonWriter = new(httpResponseStreamWriter);
115 logger.LogTrace("Sending Invoke Response: \n {InvokeResponse} with status: {Status} \n", System.Text.Json.JsonSerializer.Serialize(invokeResponse.Body, _writeIndentedJsonOptions), invokeResponse.Status);
116 if (invokeResponse.Body is not null)
117 {
118 Microsoft.Bot.Builder.Integration.AspNet.Core.HttpHelper.BotMessageSerializer.Serialize(httpResponseJsonWriter, invokeResponse.Body);
119 }
120 }
121 else
122 {
123 logger.LogWarning("HTTP response is null or has started. Cannot write invoke response. ResponseStarted: {ResponseStarted}", response?.HasStarted);
124 }
125 }
126}
127