From 1e4a474beb2e1ecf47e3566a701977518ef3e8dd Mon Sep 17 00:00:00 2001 From: Rikitav Date: Fri, 6 Mar 2026 20:49:32 +0400 Subject: [PATCH] * Simplified creation of webhost * Removed dependency from TelegramBotWebHost abstraction insode Webhooker * Added extension methods for ASP.NET host --- .../Polling/HostedUpdateWebhooker.cs | 9 +- Telegrator.Hosting.Web/TelegramBotWebHost.cs | 37 +----- .../TelegramBotWebHostBuilder.cs | 2 + Telegrator.Hosting.Web/TypesExtensions.cs | 114 +++++++++++++++++- .../Components/ITelegramBotHostBuilder.cs | 1 - .../Providers/HostHandlersCollection.cs | 2 +- .../LocalizedMessageHandlerExtensions.cs | 4 +- 7 files changed, 124 insertions(+), 45 deletions(-) diff --git a/Telegrator.Hosting.Web/Polling/HostedUpdateWebhooker.cs b/Telegrator.Hosting.Web/Polling/HostedUpdateWebhooker.cs index 7efc0e1..b66e142 100644 --- a/Telegrator.Hosting.Web/Polling/HostedUpdateWebhooker.cs +++ b/Telegrator.Hosting.Web/Polling/HostedUpdateWebhooker.cs @@ -1,12 +1,12 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; using System.Text.Json; using Telegram.Bot; using Telegram.Bot.Types; -using Telegrator.Hosting.Web.Components; using Telegrator.MadiatorCore; namespace Telegrator.Hosting.Web.Polling @@ -18,7 +18,7 @@ namespace Telegrator.Hosting.Web.Polling { private const string SecretTokenHeader = "X-Telegram-Bot-Api-Secret-Token"; - private readonly ITelegramBotWebHost _botHost; + private readonly IEndpointRouteBuilder _botHost; private readonly ITelegramBotClient _botClient; private readonly IUpdateRouter _updateRouter; private readonly TelegratorWebOptions _options; @@ -31,7 +31,7 @@ namespace Telegrator.Hosting.Web.Polling /// /// /// - public HostedUpdateWebhooker(ITelegramBotWebHost botHost, ITelegramBotClient botClient, IUpdateRouter updateRouter, IOptions options) + public HostedUpdateWebhooker(IEndpointRouteBuilder botHost, ITelegramBotClient botClient, IUpdateRouter updateRouter, IOptions options) { if (string.IsNullOrEmpty(options.Value.WebhookUri)) throw new ArgumentNullException(nameof(options), "Option \"WebhookUrl\" must be set to subscribe for update recieving"); @@ -57,8 +57,9 @@ namespace Telegrator.Hosting.Web.Polling await _botClient.SetWebhook( url: _options.WebhookUri, maxConnections: _options.MaxConnections, - allowedUpdates: _botHost.UpdateRouter.HandlersProvider.AllowedTypes, + allowedUpdates: _updateRouter.HandlersProvider.AllowedTypes, dropPendingUpdates: _options.DropPendingUpdates, + secretToken: _options.SecretToken, cancellationToken: cancellationToken); } diff --git a/Telegrator.Hosting.Web/TelegramBotWebHost.cs b/Telegrator.Hosting.Web/TelegramBotWebHost.cs index 207e075..29220f7 100644 --- a/Telegrator.Hosting.Web/TelegramBotWebHost.cs +++ b/Telegrator.Hosting.Web/TelegramBotWebHost.cs @@ -64,16 +64,11 @@ namespace Telegrator.Hosting.Web // Building proxy application _innerApp = webApplicationBuilder.Build(); - - // Initializing bot info, as it requires to make a request via tg bot - Services.GetRequiredService(); + _innerApp.UseTelegratorWeb(); // Reruesting services for this host _updateRouter = Services.GetRequiredService(); _logger = Services.GetRequiredService>(); - - // Logging registering handlers in DEBUG purposes - LogHandlers(handlers); } /// @@ -174,28 +169,6 @@ namespace Telegrator.Hosting.Web _disposed = true; } - private void LogHandlers(IHandlersCollection handlers) - { - StringBuilder logBuilder = new StringBuilder("Registered handlers : "); - if (!handlers.Keys.Any()) - throw new Exception(); - - foreach (UpdateType updateType in handlers.Keys) - { - HandlerDescriptorList descriptors = handlers[updateType]; - logBuilder.Append("\n\tUpdateType." + updateType + " :"); - - foreach (HandlerDescriptor descriptor in descriptors.Reverse()) - { - logBuilder.AppendFormat("\n\t* {0} - {1}", - descriptor.Indexer.ToString(), - descriptor.ToString()); - } - } - - Logger.LogInformation(logBuilder.ToString()); - } - private void RegisterHostServices(IServiceCollection services, IHandlersCollection handlers) { //service.RemoveAll(); @@ -204,14 +177,6 @@ namespace Telegrator.Hosting.Web services.AddSingleton(this); services.AddSingleton(this); services.AddSingleton(this); - services.AddSingleton(handlers); - - if (handlers is IHandlersManager manager) - { - services.RemoveAll(); - services.AddSingleton(manager); - services.AddSingleton(manager); - } } } } diff --git a/Telegrator.Hosting.Web/TelegramBotWebHostBuilder.cs b/Telegrator.Hosting.Web/TelegramBotWebHostBuilder.cs index ff4a744..1ba59e9 100644 --- a/Telegrator.Hosting.Web/TelegramBotWebHostBuilder.cs +++ b/Telegrator.Hosting.Web/TelegramBotWebHostBuilder.cs @@ -61,6 +61,8 @@ namespace Telegrator.Hosting.Web _innerBuilder = webApplicationBuilder ?? throw new ArgumentNullException(nameof(webApplicationBuilder)); _settings = settings ?? throw new ArgumentNullException(nameof(settings)); _handlers = handlers ?? throw new ArgumentNullException(nameof(settings)); + + _innerBuilder.AddTelegratorWeb(settings); } /// diff --git a/Telegrator.Hosting.Web/TypesExtensions.cs b/Telegrator.Hosting.Web/TypesExtensions.cs index 1482802..0758647 100644 --- a/Telegrator.Hosting.Web/TypesExtensions.cs +++ b/Telegrator.Hosting.Web/TypesExtensions.cs @@ -1,8 +1,20 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using System.Diagnostics; +using System.Text; using Telegram.Bot; +using Telegram.Bot.Types.Enums; +using Telegrator.Configuration; +using Telegrator.Hosting.Providers; +using Telegrator.Hosting.Providers.Components; using Telegrator.Hosting.Web.Components; using Telegrator.Hosting.Web.Polling; +using Telegrator.MadiatorCore; +using Telegrator.MadiatorCore.Descriptors; namespace Telegrator.Hosting.Web { @@ -12,6 +24,84 @@ namespace Telegrator.Hosting.Web /// public static class ServicesCollectionExtensions { + /// + /// Replaces TelegramBotWebHostBuilder. Configures DI, options, and handlers. + /// + public static WebApplicationBuilder AddTelegratorWeb(this WebApplicationBuilder builder, TelegramBotWebOptions settings, IHandlersCollection? handlers = null) + { + if (settings is null) + throw new ArgumentNullException(nameof(settings)); + + IServiceCollection services = builder.Services; + ConfigurationManager configuration = builder.Configuration; + + handlers ??= new HostHandlersCollection(services, settings); + + if (handlers is IHostHandlersCollection hostHandlers) + { + foreach (PreBuildingRoutine preBuildRoutine in hostHandlers.PreBuilderRoutines) + { + try + { + // TODO: fix + //preBuildRoutine.Invoke(builder); + Debug.WriteLine("Pre-Building routine was not executed"); + } + catch (NotImplementedException) + { + _ = 0xBAD + 0xC0DE; + } + } + } + + if (!settings.DisableAutoConfigure) + { + services.Configure(configuration.GetSection(nameof(TelegratorWebOptions))); + } + else + { + if (!services.Any(srvc => srvc.ImplementationType == typeof(IOptions))) + throw new MissingMemberException("Auto configuration disabled, yet no options of type 'TelegratorWebOptions' wasn't registered. This configuration is runtime required!"); + + if (!services.Any(srvc => srvc.ImplementationType == typeof(IOptions))) + throw new MissingMemberException("Auto configuration disabled, yet no options of type 'TelegramBotClientOptions' wasn't registered. This configuration is runtime required!"); + } + + IOptions options = Options.Create(settings); + services.AddSingleton((IOptions)options); + services.AddSingleton(options); + services.AddSingleton(handlers); + + if (handlers is IHandlersManager manager) + { + ServiceDescriptor descriptor = new ServiceDescriptor(typeof(IHandlersProvider), manager); + services.Replace(descriptor); + services.AddSingleton(manager); + } + + services.AddTelegramBotHostDefaults(); + services.AddTelegramWebhook(); + + return builder; + } + + /// + /// Replaces the initialization logic from TelegramBotWebHost constructor. + /// Initializes the bot and logs handlers on application startup. + /// + public static WebApplication UseTelegratorWeb(this WebApplication app) + { + ITelegramBotInfo info = app.Services.GetRequiredService(); + IHandlersCollection handlers = app.Services.GetRequiredService(); + ILoggerFactory loggerFactory = app.Services.GetRequiredService(); + ILogger logger = loggerFactory.CreateLogger("Telegrator.Hosting.Web.TelegratorHost"); + + logger.LogInformation("Telegrator Bot WebHost started"); + LogHandlers(handlers, logger); + + return app; + } + /// /// Registers service with to receive updates using webhook /// @@ -26,5 +116,27 @@ namespace Telegrator.Hosting.Web private static ITelegramBotClient TypedTelegramBotClientFactory(HttpClient httpClient, IServiceProvider provider) => new TelegramBotClient(provider.GetRequiredService>().Value, httpClient); + + private static void LogHandlers(IHandlersCollection handlers, ILogger logger) + { + if (!handlers.Keys.Any()) + throw new Exception("No handlers were registered for the bot."); + + StringBuilder logBuilder = new StringBuilder("Registered handlers : "); + foreach (UpdateType updateType in handlers.Keys) + { + HandlerDescriptorList descriptors = handlers[updateType]; + logBuilder.Append("\n\tUpdateType." + updateType + " :"); + + foreach (HandlerDescriptor descriptor in Enumerable.Reverse(descriptors)) + { + logBuilder.AppendFormat("\n\t* {0} - {1}", + descriptor.Indexer.ToString(), + descriptor.ToString()); + } + } + + logger.LogInformation(logBuilder.ToString()); + } } } diff --git a/Telegrator.Hosting/Components/ITelegramBotHostBuilder.cs b/Telegrator.Hosting/Components/ITelegramBotHostBuilder.cs index 59a1810..69b40bd 100644 --- a/Telegrator.Hosting/Components/ITelegramBotHostBuilder.cs +++ b/Telegrator.Hosting/Components/ITelegramBotHostBuilder.cs @@ -1,6 +1,5 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Telegrator.MadiatorCore; diff --git a/Telegrator.Hosting/Providers/HostHandlersCollection.cs b/Telegrator.Hosting/Providers/HostHandlersCollection.cs index cc76683..eb4a95d 100644 --- a/Telegrator.Hosting/Providers/HostHandlersCollection.cs +++ b/Telegrator.Hosting/Providers/HostHandlersCollection.cs @@ -13,7 +13,7 @@ namespace Telegrator.Hosting.Providers /// Pre host building task /// /// - public delegate void PreBuildingRoutine(ITelegramBotHostBuilder builder); + public delegate void PreBuildingRoutine(IApplicationBuilder builder); /// public class HostHandlersCollection(IServiceCollection hostServiceColletion, ITelegratorOptions options) : HandlersCollection(options), IHostHandlersCollection diff --git a/Telegrator.Localized/LocalizedMessageHandlerExtensions.cs b/Telegrator.Localized/LocalizedMessageHandlerExtensions.cs index 7957cd7..9505566 100644 --- a/Telegrator.Localized/LocalizedMessageHandlerExtensions.cs +++ b/Telegrator.Localized/LocalizedMessageHandlerExtensions.cs @@ -10,8 +10,8 @@ namespace Telegrator.Localized { public static async Task ResponseLocalized(this ILocalizedHandler localizedHandler, string localizedReplyIdentifier, params IEnumerable formatArgs) { - LocalizedString localizedString = localizedHandler.LocalizationProvider[localizedReplyIdentifier]; - localizedHandler.Container.Response(); + LocalizedString localizedString = localizedHandler.LocalizationProvider[localizedReplyIdentifier, formatArgs]; + return await localizedHandler.Container.Responce(localizedString.Value); } } }