using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using System.Text; using Telegram.Bot.Types.Enums; using Telegrator.Configuration; using Telegrator.Hosting.Components; using Telegrator.Hosting.Web.Components; using Telegrator.MadiatorCore; using Telegrator.MadiatorCore.Descriptors; namespace Telegrator.Hosting.Web { /// /// Represents a web hosted telegram bot /// public class TelegramBotWebHost : ITelegramBotWebHost { private readonly WebApplication _innerApp; private readonly IUpdateRouter _updateRouter; private readonly ILogger _logger; private bool _disposed; /// public IServiceProvider Services => _innerApp.Services; /// public IUpdateRouter UpdateRouter => _updateRouter; /// public ICollection DataSources => ((IEndpointRouteBuilder)_innerApp).DataSources; /// /// Allows consumers to be notified of application lifetime events. /// public IHostApplicationLifetime Lifetime => _innerApp.Lifetime; /// /// This application's logger /// public ILogger Logger => _logger; // Private interface fields IServiceProvider IEndpointRouteBuilder.ServiceProvider => Services; IServiceProvider IApplicationBuilder.ApplicationServices { get => Services; set => throw new NotImplementedException(); } IFeatureCollection IApplicationBuilder.ServerFeatures => ((IApplicationBuilder)_innerApp).ServerFeatures; IDictionary IApplicationBuilder.Properties => ((IApplicationBuilder)_innerApp).Properties; /// /// Initializes a new instance of the class. /// /// The proxied instance of host builder. /// public TelegramBotWebHost(WebApplicationBuilder webApplicationBuilder, IHandlersCollection handlers) { // Registering this host in services for easy access RegisterHostServices(webApplicationBuilder.Services, handlers); // Building proxy application _innerApp = webApplicationBuilder.Build(); _innerApp.UseTelegratorWeb(); // Reruesting services for this host _updateRouter = Services.GetRequiredService(); _logger = Services.GetRequiredService>(); } /// /// Creates new with default services and webhook update receiving scheme /// /// public static TelegramBotWebHostBuilder CreateBuilder(TelegramBotWebOptions settings) { ArgumentNullException.ThrowIfNull(settings, nameof(settings)); WebApplicationBuilder innerApp = WebApplication.CreateBuilder(settings.ToWebApplicationOptions()); TelegramBotWebHostBuilder builder = new TelegramBotWebHostBuilder(innerApp, settings); builder.Services.AddTelegramBotHostDefaults(); builder.Services.AddTelegramWebhook(); return builder; } /// /// Creates new SLIM with default services and webhook update receiving scheme /// /// public static TelegramBotWebHostBuilder CreateSlimBuilder(TelegramBotWebOptions settings) { ArgumentNullException.ThrowIfNull(settings, nameof(settings)); WebApplicationBuilder innerApp = WebApplication.CreateSlimBuilder(settings.ToWebApplicationOptions()); TelegramBotWebHostBuilder builder = new TelegramBotWebHostBuilder(innerApp, settings); builder.Services.AddTelegramBotHostDefaults(); builder.Services.AddTelegramWebhook(); return builder; } /// /// Creates new EMPTY WITHOUT any services or update receiving schemes /// /// public static TelegramBotWebHostBuilder CreateEmptyBuilder(TelegramBotWebOptions settings) { ArgumentNullException.ThrowIfNull(settings, nameof(settings)); WebApplicationBuilder innerApp = WebApplication.CreateEmptyBuilder(settings.ToWebApplicationOptions()); return new TelegramBotWebHostBuilder(innerApp, settings); } /// public async Task StartAsync(CancellationToken cancellationToken = default) { await _innerApp.StartAsync(cancellationToken); } /// public async Task StopAsync(CancellationToken cancellationToken = default) { await _innerApp.StopAsync(cancellationToken); } /// public IApplicationBuilder CreateApplicationBuilder() => ((IEndpointRouteBuilder)_innerApp).CreateApplicationBuilder(); /// public IApplicationBuilder Use(Func middleware) => _innerApp.Use(middleware); /// public IApplicationBuilder New() => ((IApplicationBuilder)_innerApp).New(); /// public RequestDelegate Build() => ((IApplicationBuilder)_innerApp).Build(); /// /// Disposes the host. /// public async ValueTask DisposeAsync() { if (_disposed) return; await _innerApp.DisposeAsync(); GC.SuppressFinalize(this); _disposed = true; } /// /// Disposes the host. /// public void Dispose() { if (_disposed) return; // Sorry for this, i really dont know how to handle such cases ValueTask disposeTask = _innerApp.DisposeAsync(); while (!disposeTask.IsCompleted) Thread.Sleep(100); GC.SuppressFinalize(this); _disposed = true; } private void RegisterHostServices(IServiceCollection services, IHandlersCollection handlers) { //service.RemoveAll(); //service.AddSingleton(this); services.AddSingleton(this); services.AddSingleton(this); services.AddSingleton(this); } } }