microsoft/teams.net

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
c9613c042b5302aa50b0e4a195512cab276ef100

Branches

Tags

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

Clone

HTTPS

Download ZIP

core/src/Microsoft.Bot.Core/BotApplication.cs

136lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using Microsoft.AspNetCore.Http;
5using Microsoft.Bot.Core.Hosting;
6using Microsoft.Bot.Core.Schema;
7using Microsoft.Extensions.Configuration;
8using Microsoft.Extensions.Logging;
9
10namespace Microsoft.Bot.Core;
11
12/// <summary>
13/// Represents a bot application.
14/// </summary>
15public class BotApplication
16{
17 private readonly ILogger<BotApplication> _logger;
18 private readonly ConversationClient? _conversationClient;
19 private readonly string _serviceKey;
20 internal TurnMiddleware MiddleWare { get; }
21
22 /// <summary>
23 /// Initializes a new instance of the BotApplication class with the specified conversation client, configuration,
24 /// logger, and optional service key.
25 /// </summary>
26 /// <remarks>This constructor sets up the bot application and starts the bot listener using the provided
27 /// configuration and service key. The service key is used to locate authentication credentials in the
28 /// configuration.</remarks>
29 /// <param name="conversationClient">The client used to manage and interact with conversations for the bot.</param>
30 /// <param name="config">The application configuration settings used to retrieve environment variables and service credentials.</param>
31 /// <param name="logger">The logger used to record operational and diagnostic information for the bot application.</param>
32 /// <param name="serviceKey">The configuration key identifying the authentication service. Defaults to "AzureAd" if not specified.</param>
33 [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1848:Use the LoggerMessage delegates", Justification = "<Pending>")]
34 public BotApplication(ConversationClient conversationClient, IConfiguration config, ILogger<BotApplication> logger, string serviceKey = "AzureAd")
35 {
36 _logger = logger;
37 _serviceKey = serviceKey;
38 MiddleWare = new TurnMiddleware();
39 _conversationClient = conversationClient;
40 logger.LogInformation("Started bot listener on {Port} for AppID:{AppId} with SDK version {SdkVersion}", config?["ASPNETCORE_URLS"], config?[$"{_serviceKey}:ClientId"], Version);
41 }
42
43
44 /// <summary>
45 /// Gets the client used to manage and interact with conversations.
46 /// </summary>
47 /// <remarks>Accessing this property before the client is initialized will result in an exception. Ensure
48 /// that the client is properly configured before use.</remarks>
49 public ConversationClient ConversationClient => _conversationClient ?? throw new InvalidOperationException("ConversationClient not initialized");
50
51 /// <summary>
52 /// Gets or sets the delegate that is invoked to handle an incoming activity asynchronously.
53 /// </summary>
54 /// <remarks>Assign a delegate to process activities as they are received. The delegate should accept an
55 /// <see cref="CoreActivity"/> and a <see cref="CancellationToken"/>, and return a <see cref="Task"/> representing the
56 /// asynchronous operation. If <see langword="null"/>, incoming activities will not be handled.</remarks>
57 public Func<CoreActivity, CancellationToken, Task>? OnActivity { get; set; }
58
59 /// <summary>
60 /// Processes an incoming HTTP request containing a bot activity.
61 /// </summary>
62 /// <param name="httpContext"></param>
63 /// <param name="cancellationToken"></param>
64 /// <returns></returns>
65 /// <exception cref="InvalidOperationException"></exception>
66 /// <exception cref="BotHandlerException"></exception>
67 [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1848:Use the LoggerMessage delegates", Justification = "<Pending>")]
68 public async Task<CoreActivity> ProcessAsync(HttpContext httpContext, CancellationToken cancellationToken = default)
69 {
70 ArgumentNullException.ThrowIfNull(httpContext);
71 ArgumentNullException.ThrowIfNull(_conversationClient);
72
73 _logger.LogDebug("Start processing HTTP request for activity");
74
75 CoreActivity activity = await CoreActivity.FromJsonStreamAsync(httpContext.Request.Body, cancellationToken).ConfigureAwait(false) ?? throw new InvalidOperationException("Invalid Activity");
76
77 _logger.LogInformation("Processing activity: {Id} {Type}", activity.Id, activity.Type);
78
79 if (_logger.IsEnabled(LogLevel.Trace))
80 {
81 _logger.LogTrace("Received activity: {Activity}", activity.ToJson());
82 }
83
84 AgenticIdentity? agenticIdentity = AgenticIdentity.FromProperties(activity.Recipient.Properties);
85 _conversationClient.AgenticIdentity = agenticIdentity;
86
87 using (_logger.BeginScope("Processing activity {Type} {Id}", activity.Type, activity.Id))
88 {
89 try
90 {
91 await MiddleWare.RunPipelineAsync(this, activity, this.OnActivity, 0, cancellationToken).ConfigureAwait(false);
92 }
93 catch (Exception ex)
94 {
95 _logger.LogError(ex, "Error processing activity {Type} {Id}", activity.Type, activity.Id);
96 throw new BotHandlerException("Error processing activity", ex, activity);
97 }
98 finally
99 {
100 _logger.LogInformation("Finished processing activity {Type} {Id}", activity.Type, activity.Id);
101 }
102 return activity;
103 }
104 }
105
106 /// <summary>
107 /// Adds the specified turn middleware to the middleware pipeline.
108 /// </summary>
109 /// <param name="middleware">The middleware component to add to the pipeline. Cannot be null.</param>
110 /// <returns>An ITurnMiddleWare instance representing the updated middleware pipeline.</returns>
111 public ITurnMiddleWare Use(ITurnMiddleWare middleware)
112 {
113 MiddleWare.Use(middleware);
114 return MiddleWare;
115 }
116
117 /// <summary>
118 /// Sends the specified activity to the conversation asynchronously.
119 /// </summary>
120 /// <param name="activity">The activity to send to the conversation. Cannot be null.</param>
121 /// <param name="cancellationToken">A cancellation token that can be used to cancel the send operation.</param>
122 /// <returns>A task that represents the asynchronous operation. The task result contains the identifier of the sent activity.</returns>
123 /// <exception cref="Exception">Thrown if the conversation client has not been initialized.</exception>
124 public async Task<string> SendActivityAsync(CoreActivity activity, CancellationToken cancellationToken = default)
125 {
126 ArgumentNullException.ThrowIfNull(activity);
127 ArgumentNullException.ThrowIfNull(_conversationClient, "ConversationClient not initialized");
128
129 return await _conversationClient.SendActivityAsync(activity, cancellationToken).ConfigureAwait(false);
130 }
131
132 /// <summary>
133 /// Gets the version of the SDK.
134 /// </summary>
135 public static string Version => ThisAssembly.NuGetPackageVersion;
136}
137