* Simplified creation of webhost

* Removed dependency from TelegramBotWebHost abstraction insode Webhooker
* Added extension methods for ASP.NET host
This commit is contained in:
2026-03-06 20:49:32 +04:00
parent 52ebda68fe
commit 1e4a474beb
7 changed files with 124 additions and 45 deletions
@@ -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
/// <param name="updateRouter"></param>
/// <param name="options"></param>
/// <exception cref="ArgumentNullException"></exception>
public HostedUpdateWebhooker(ITelegramBotWebHost botHost, ITelegramBotClient botClient, IUpdateRouter updateRouter, IOptions<TelegratorWebOptions> options)
public HostedUpdateWebhooker(IEndpointRouteBuilder botHost, ITelegramBotClient botClient, IUpdateRouter updateRouter, IOptions<TelegratorWebOptions> 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);
}
+1 -36
View File
@@ -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<ITelegramBotInfo>();
_innerApp.UseTelegratorWeb();
// Reruesting services for this host
_updateRouter = Services.GetRequiredService<IUpdateRouter>();
_logger = Services.GetRequiredService<ILogger<TelegramBotWebHost>>();
// Logging registering handlers in DEBUG purposes
LogHandlers(handlers);
}
/// <summary>
@@ -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<IHost>();
@@ -204,14 +177,6 @@ namespace Telegrator.Hosting.Web
services.AddSingleton<ITelegramBotHost>(this);
services.AddSingleton<ITelegramBotWebHost>(this);
services.AddSingleton<ITelegratorBot>(this);
services.AddSingleton(handlers);
if (handlers is IHandlersManager manager)
{
services.RemoveAll<IHandlersProvider>();
services.AddSingleton<IHandlersProvider>(manager);
services.AddSingleton(manager);
}
}
}
}
@@ -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);
}
/// <summary>
+113 -1
View File
@@ -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
/// </summary>
public static class ServicesCollectionExtensions
{
/// <summary>
/// Replaces TelegramBotWebHostBuilder. Configures DI, options, and handlers.
/// </summary>
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<TelegratorWebOptions>(configuration.GetSection(nameof(TelegratorWebOptions)));
}
else
{
if (!services.Any(srvc => srvc.ImplementationType == typeof(IOptions<TelegratorWebOptions>)))
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<TelegramBotClientOptions>)))
throw new MissingMemberException("Auto configuration disabled, yet no options of type 'TelegramBotClientOptions' wasn't registered. This configuration is runtime required!");
}
IOptions<TelegramBotWebOptions> options = Options.Create(settings);
services.AddSingleton((IOptions<TelegratorOptions>)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;
}
/// <summary>
/// Replaces the initialization logic from TelegramBotWebHost constructor.
/// Initializes the bot and logs handlers on application startup.
/// </summary>
public static WebApplication UseTelegratorWeb(this WebApplication app)
{
ITelegramBotInfo info = app.Services.GetRequiredService<ITelegramBotInfo>();
IHandlersCollection handlers = app.Services.GetRequiredService<IHandlersCollection>();
ILoggerFactory loggerFactory = app.Services.GetRequiredService<ILoggerFactory>();
ILogger logger = loggerFactory.CreateLogger("Telegrator.Hosting.Web.TelegratorHost");
logger.LogInformation("Telegrator Bot WebHost started");
LogHandlers(handlers, logger);
return app;
}
/// <summary>
/// Registers <see cref="ITelegramBotClient"/> service with <see cref="HostedUpdateWebhooker"/> to receive updates using webhook
/// </summary>
@@ -26,5 +116,27 @@ namespace Telegrator.Hosting.Web
private static ITelegramBotClient TypedTelegramBotClientFactory(HttpClient httpClient, IServiceProvider provider)
=> new TelegramBotClient(provider.GetRequiredService<IOptions<TelegramBotClientOptions>>().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());
}
}
}