* Syntaxual refactoring

This commit is contained in:
2026-03-09 13:23:21 +04:00
parent 899243c62b
commit 79d5df8291
130 changed files with 9679 additions and 9831 deletions
@@ -3,28 +3,27 @@ using Telegram.Bot;
using Telegram.Bot.Types;
using Telegrator.Core;
namespace Telegrator.Hosting
{
/// <summary>
/// Implementation of <see cref="ITelegramBotInfo"/> that provides bot information.
/// Contains metadata about the Telegram bot including user details and service provider for wider filterring abilities
/// </summary>
/// <param name="client"></param>
/// <param name="services"></param>
/// <param name="configuration"></param>
public class HostedTelegramBotInfo(ITelegramBotClient client, IServiceProvider services, IConfiguration configuration) : ITelegramBotInfo
{
/// <inheritdoc/>
public User User { get; } = client.GetMe().Result;
/// <summary>
/// Provides access to services of this Hosted telegram bot
/// </summary>
public IServiceProvider Services { get; } = services;
namespace Telegrator.Hosting;
/// <summary>
/// Provides access to configuration of this Hosted telegram bot
/// </summary>
public IConfiguration Configuration { get; } = configuration;
}
/// <summary>
/// Implementation of <see cref="ITelegramBotInfo"/> that provides bot information.
/// Contains metadata about the Telegram bot including user details and service provider for wider filterring abilities
/// </summary>
/// <param name="client"></param>
/// <param name="services"></param>
/// <param name="configuration"></param>
public class HostedTelegramBotInfo(ITelegramBotClient client, IServiceProvider services, IConfiguration configuration) : ITelegramBotInfo
{
/// <inheritdoc/>
public User User { get; } = client.GetMe().Result;
/// <summary>
/// Provides access to services of this Hosted telegram bot
/// </summary>
public IServiceProvider Services { get; } = services;
/// <summary>
/// Provides access to configuration of this Hosted telegram bot
/// </summary>
public IConfiguration Configuration { get; } = configuration;
}
@@ -3,113 +3,112 @@ using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Telegrator.Core;
namespace Telegrator.Hosting
namespace Telegrator.Hosting;
/// <summary>
/// Represents a hosted telegram bot
/// </summary>
public class TelegramBotHost : IHost, ITelegratorBot
{
private readonly IHost _innerHost;
private readonly IUpdateRouter _updateRouter;
private readonly ILogger<TelegramBotHost> _logger;
private bool _disposed;
/// <inheritdoc/>
public IServiceProvider Services => _innerHost.Services;
/// <inheritdoc/>
public IUpdateRouter UpdateRouter => _updateRouter;
/// <summary>
/// Represents a hosted telegram bot
/// This application's logger
/// </summary>
public class TelegramBotHost : IHost, ITelegratorBot
public ILogger<TelegramBotHost> Logger => _logger;
/// <summary>
/// Initializes a new instance of the <see cref="TelegramBotHost"/> class.
/// </summary>
/// <param name="hostApplicationBuilder">The proxied instance of host builder.</param>
public TelegramBotHost(HostApplicationBuilder hostApplicationBuilder)
{
private readonly IHost _innerHost;
private readonly IUpdateRouter _updateRouter;
private readonly ILogger<TelegramBotHost> _logger;
// Registering this host in services for easy access
hostApplicationBuilder.Services.AddSingleton<ITelegratorBot>(this);
private bool _disposed;
// Building proxy hoster
_innerHost = hostApplicationBuilder.Build();
/// <inheritdoc/>
public IServiceProvider Services => _innerHost.Services;
// Reruesting services for this host
_updateRouter = Services.GetRequiredService<IUpdateRouter>();
_logger = Services.GetRequiredService<ILogger<TelegramBotHost>>();
}
/// <inheritdoc/>
public IUpdateRouter UpdateRouter => _updateRouter;
/// <summary>
/// Creates new <see cref="TelegramBotHostBuilder"/> with default configuration, services and long-polling update receiving scheme
/// </summary>
/// <returns></returns>
public static TelegramBotHostBuilder CreateBuilder()
{
HostApplicationBuilder innerBuilder = new HostApplicationBuilder(settings: null);
TelegramBotHostBuilder builder = new TelegramBotHostBuilder(innerBuilder, null);
return builder;
}
/// <summary>
/// This application's logger
/// </summary>
public ILogger<TelegramBotHost> Logger => _logger;
/// <summary>
/// Creates new <see cref="TelegramBotHostBuilder"/> with default services and long-polling update receiving scheme
/// </summary>
/// <returns></returns>
public static TelegramBotHostBuilder CreateBuilder(HostApplicationBuilderSettings? settings)
{
HostApplicationBuilder innerBuilder = new HostApplicationBuilder(settings);
TelegramBotHostBuilder builder = new TelegramBotHostBuilder(innerBuilder, settings);
return builder;
}
/// <summary>
/// Initializes a new instance of the <see cref="TelegramBotHost"/> class.
/// </summary>
/// <param name="hostApplicationBuilder">The proxied instance of host builder.</param>
public TelegramBotHost(HostApplicationBuilder hostApplicationBuilder)
{
// Registering this host in services for easy access
hostApplicationBuilder.Services.AddSingleton<ITelegratorBot>(this);
/// <summary>
/// Creates new EMPTY <see cref="TelegramBotHostBuilder"/> WITHOUT any services or update receiving schemes
/// </summary>
/// <returns></returns>
public static TelegramBotHostBuilder CreateEmptyBuilder()
{
HostApplicationBuilder innerBuilder = Host.CreateEmptyApplicationBuilder(null);
return new TelegramBotHostBuilder(innerBuilder, null);
}
// Building proxy hoster
_innerHost = hostApplicationBuilder.Build();
/// <summary>
/// Creates new EMPTY <see cref="TelegramBotHostBuilder"/> WITHOUT any services or update receiving schemes
/// </summary>
/// <returns></returns>
public static TelegramBotHostBuilder CreateEmptyBuilder(HostApplicationBuilderSettings? settings)
{
HostApplicationBuilder innerBuilder = Host.CreateEmptyApplicationBuilder(null);
return new TelegramBotHostBuilder(innerBuilder, settings);
}
// Reruesting services for this host
_updateRouter = Services.GetRequiredService<IUpdateRouter>();
_logger = Services.GetRequiredService<ILogger<TelegramBotHost>>();
}
/// <inheritdoc/>
public async Task StartAsync(CancellationToken cancellationToken = default)
{
await _innerHost.StartAsync(cancellationToken);
}
/// <summary>
/// Creates new <see cref="TelegramBotHostBuilder"/> with default configuration, services and long-polling update receiving scheme
/// </summary>
/// <returns></returns>
public static TelegramBotHostBuilder CreateBuilder()
{
HostApplicationBuilder innerBuilder = new HostApplicationBuilder(settings: null);
TelegramBotHostBuilder builder = new TelegramBotHostBuilder(innerBuilder, null);
return builder;
}
/// <inheritdoc/>
public async Task StopAsync(CancellationToken cancellationToken = default)
{
await _innerHost.StopAsync(cancellationToken);
}
/// <summary>
/// Creates new <see cref="TelegramBotHostBuilder"/> with default services and long-polling update receiving scheme
/// </summary>
/// <returns></returns>
public static TelegramBotHostBuilder CreateBuilder(HostApplicationBuilderSettings? settings)
{
HostApplicationBuilder innerBuilder = new HostApplicationBuilder(settings);
TelegramBotHostBuilder builder = new TelegramBotHostBuilder(innerBuilder, settings);
return builder;
}
/// <summary>
/// Disposes the host.
/// </summary>
public void Dispose()
{
if (_disposed)
return;
/// <summary>
/// Creates new EMPTY <see cref="TelegramBotHostBuilder"/> WITHOUT any services or update receiving schemes
/// </summary>
/// <returns></returns>
public static TelegramBotHostBuilder CreateEmptyBuilder()
{
HostApplicationBuilder innerBuilder = Host.CreateEmptyApplicationBuilder(null);
return new TelegramBotHostBuilder(innerBuilder, null);
}
_innerHost.Dispose();
/// <summary>
/// Creates new EMPTY <see cref="TelegramBotHostBuilder"/> WITHOUT any services or update receiving schemes
/// </summary>
/// <returns></returns>
public static TelegramBotHostBuilder CreateEmptyBuilder(HostApplicationBuilderSettings? settings)
{
HostApplicationBuilder innerBuilder = Host.CreateEmptyApplicationBuilder(null);
return new TelegramBotHostBuilder(innerBuilder, settings);
}
/// <inheritdoc/>
public async Task StartAsync(CancellationToken cancellationToken = default)
{
await _innerHost.StartAsync(cancellationToken);
}
/// <inheritdoc/>
public async Task StopAsync(CancellationToken cancellationToken = default)
{
await _innerHost.StopAsync(cancellationToken);
}
/// <summary>
/// Disposes the host.
/// </summary>
public void Dispose()
{
if (_disposed)
return;
_innerHost.Dispose();
GC.SuppressFinalize(this);
_disposed = true;
}
GC.SuppressFinalize(this);
_disposed = true;
}
}
@@ -3,114 +3,111 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.Metrics;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Telegrator.Core;
using Telegrator.Providers;
#pragma warning disable IDE0001
namespace Telegrator.Hosting
namespace Telegrator.Hosting;
/// <summary>
/// Represents a hosted telegram bots and services builder that helps manage configuration, logging, lifetime, and more.
/// </summary>
public class TelegramBotHostBuilder : IHostApplicationBuilder, ICollectingProvider
{
private readonly HostApplicationBuilder _innerBuilder;
private readonly HostApplicationBuilderSettings _settings;
internal IHandlersCollection _handlers = null!;
/// <inheritdoc/>
public IHandlersCollection Handlers => _handlers;
/// <inheritdoc/>
public IServiceCollection Services => _innerBuilder.Services;
/// <inheritdoc/>
public IConfigurationManager Configuration => _innerBuilder.Configuration;
/// <inheritdoc/>
public ILoggingBuilder Logging => _innerBuilder.Logging;
/// <inheritdoc/>
public IHostEnvironment Environment => _innerBuilder.Environment;
/// <inheritdoc/>
public IDictionary<object, object> Properties => ((IHostApplicationBuilder)_innerBuilder).Properties;
/// <inheritdoc/>
public IMetricsBuilder Metrics => _innerBuilder.Metrics;
/// <summary>
/// Represents a hosted telegram bots and services builder that helps manage configuration, logging, lifetime, and more.
/// Initializes a new instance of the <see cref="TelegramBotHostBuilder"/> class.
/// </summary>
public class TelegramBotHostBuilder : IHostApplicationBuilder, ICollectingProvider
/// <param name="hostApplicationBuilder"></param>
/// <param name="settings"></param>
public TelegramBotHostBuilder(HostApplicationBuilder hostApplicationBuilder, HostApplicationBuilderSettings? settings = null)
{
private readonly HostApplicationBuilder _innerBuilder;
private readonly HostApplicationBuilderSettings _settings;
internal IHandlersCollection _handlers = null!;
_innerBuilder = hostApplicationBuilder ?? throw new ArgumentNullException(nameof(hostApplicationBuilder));
_settings = settings ?? new HostApplicationBuilderSettings();
/// <inheritdoc/>
public IHandlersCollection Handlers => _handlers;
this.AddTelegrator();
}
/// <inheritdoc/>
public IServiceCollection Services => _innerBuilder.Services;
/// <summary>
/// Initializes a new instance of the <see cref="TelegramBotHostBuilder"/> class.
/// </summary>
/// <param name="hostApplicationBuilder"></param>
/// <param name="options"></param>
/// <param name="settings"></param>
public TelegramBotHostBuilder(HostApplicationBuilder hostApplicationBuilder, TelegratorOptions? options, HostApplicationBuilderSettings? settings)
{
_innerBuilder = hostApplicationBuilder ?? throw new ArgumentNullException(nameof(hostApplicationBuilder));
_settings = settings ?? new HostApplicationBuilderSettings();
/// <inheritdoc/>
public IConfigurationManager Configuration => _innerBuilder.Configuration;
this.AddTelegrator(options, null);
}
/// <inheritdoc/>
public ILoggingBuilder Logging => _innerBuilder.Logging;
/// <summary>
/// Initializes a new instance of the <see cref="TelegramBotHostBuilder"/> class.
/// </summary>
/// <param name="hostApplicationBuilder"></param>
/// <param name="handlers"></param>
/// <param name="settings"></param>
public TelegramBotHostBuilder(HostApplicationBuilder hostApplicationBuilder, IHandlersCollection handlers, HostApplicationBuilderSettings? settings)
{
_innerBuilder = hostApplicationBuilder ?? throw new ArgumentNullException(nameof(hostApplicationBuilder));
_settings = settings ?? new HostApplicationBuilderSettings();
/// <inheritdoc/>
public IHostEnvironment Environment => _innerBuilder.Environment;
this.AddTelegrator(null, handlers);
}
/// <inheritdoc/>
public IDictionary<object, object> Properties => ((IHostApplicationBuilder)_innerBuilder).Properties;
/// <summary>
/// Initializes a new instance of the <see cref="TelegramBotHostBuilder"/> class.
/// </summary>
/// <param name="hostApplicationBuilder"></param>
/// <param name="handlers"></param>
/// <param name="options"></param>
/// <param name="settings"></param>
public TelegramBotHostBuilder(HostApplicationBuilder hostApplicationBuilder, IHandlersCollection handlers, TelegratorOptions? options, HostApplicationBuilderSettings? settings)
{
_innerBuilder = hostApplicationBuilder ?? throw new ArgumentNullException(nameof(hostApplicationBuilder));
_settings = settings ?? new HostApplicationBuilderSettings();
/// <inheritdoc/>
public IMetricsBuilder Metrics => _innerBuilder.Metrics;
this.AddTelegrator(options, handlers);
}
/// <summary>
/// Initializes a new instance of the <see cref="TelegramBotHostBuilder"/> class.
/// </summary>
/// <param name="hostApplicationBuilder"></param>
/// <param name="settings"></param>
public TelegramBotHostBuilder(HostApplicationBuilder hostApplicationBuilder, HostApplicationBuilderSettings? settings = null)
{
_innerBuilder = hostApplicationBuilder ?? throw new ArgumentNullException(nameof(hostApplicationBuilder));
_settings = settings ?? new HostApplicationBuilderSettings();
/// <summary>
/// Builds the host.
/// </summary>
/// <returns></returns>
public TelegramBotHost Build()
{
TelegramBotHost host = new TelegramBotHost(_innerBuilder);
host.UseTelegrator();
return host;
}
this.AddTelegrator();
}
/// <summary>
/// Initializes a new instance of the <see cref="TelegramBotHostBuilder"/> class.
/// </summary>
/// <param name="hostApplicationBuilder"></param>
/// <param name="options"></param>
/// <param name="settings"></param>
public TelegramBotHostBuilder(HostApplicationBuilder hostApplicationBuilder, TelegratorOptions? options, HostApplicationBuilderSettings? settings)
{
_innerBuilder = hostApplicationBuilder ?? throw new ArgumentNullException(nameof(hostApplicationBuilder));
_settings = settings ?? new HostApplicationBuilderSettings();
this.AddTelegrator(options, null);
}
/// <summary>
/// Initializes a new instance of the <see cref="TelegramBotHostBuilder"/> class.
/// </summary>
/// <param name="hostApplicationBuilder"></param>
/// <param name="handlers"></param>
/// <param name="settings"></param>
public TelegramBotHostBuilder(HostApplicationBuilder hostApplicationBuilder, IHandlersCollection handlers, HostApplicationBuilderSettings? settings)
{
_innerBuilder = hostApplicationBuilder ?? throw new ArgumentNullException(nameof(hostApplicationBuilder));
_settings = settings ?? new HostApplicationBuilderSettings();
this.AddTelegrator(null, handlers);
}
/// <summary>
/// Initializes a new instance of the <see cref="TelegramBotHostBuilder"/> class.
/// </summary>
/// <param name="hostApplicationBuilder"></param>
/// <param name="handlers"></param>
/// <param name="options"></param>
/// <param name="settings"></param>
public TelegramBotHostBuilder(HostApplicationBuilder hostApplicationBuilder, IHandlersCollection handlers, TelegratorOptions? options, HostApplicationBuilderSettings? settings)
{
_innerBuilder = hostApplicationBuilder ?? throw new ArgumentNullException(nameof(hostApplicationBuilder));
_settings = settings ?? new HostApplicationBuilderSettings();
this.AddTelegrator(options, handlers);
}
/// <summary>
/// Builds the host.
/// </summary>
/// <returns></returns>
public TelegramBotHost Build()
{
TelegramBotHost host = new TelegramBotHost(_innerBuilder);
host.UseTelegrator();
return host;
}
/// <inheritdoc/>
public void ConfigureContainer<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory, Action<TContainerBuilder>? configure = null) where TContainerBuilder : notnull
{
this.ConfigureContainer(factory, configure);
}
/// <inheritdoc/>
public void ConfigureContainer<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory, Action<TContainerBuilder>? configure = null) where TContainerBuilder : notnull
{
this.ConfigureContainer(factory, configure);
}
}
@@ -1,45 +1,42 @@
using Microsoft.Extensions.Logging;
namespace Telegrator.Logging;
namespace Telegrator.Logging
/// <summary>
/// Adapter for Microsoft.Extensions.Logging to work with Telegrator logging system.
/// This allows seamless integration with ASP.NET Core logging infrastructure.
/// </summary>
public class MicrosoftLoggingAdapter : ITelegratorLogger
{
private readonly Microsoft.Extensions.Logging.ILogger _logger;
/// <summary>
/// Adapter for Microsoft.Extensions.Logging to work with Telegrator logging system.
/// This allows seamless integration with ASP.NET Core logging infrastructure.
/// Initializes a new instance of MicrosoftLoggingAdapter.
/// </summary>
public class MicrosoftLoggingAdapter : ITelegratorLogger
/// <param name="logger">The Microsoft.Extensions.Logging logger instance.</param>
public MicrosoftLoggingAdapter(Microsoft.Extensions.Logging.ILogger logger)
{
private readonly ILogger _logger;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
/// <summary>
/// Initializes a new instance of MicrosoftLoggingAdapter.
/// </summary>
/// <param name="logger">The Microsoft.Extensions.Logging logger instance.</param>
public MicrosoftLoggingAdapter(ILogger logger)
/// <inheritdoc/>
public void Log(LogLevel level, string message, Exception? exception = null)
{
var msLogLevel = level switch
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
LogLevel.Trace => Microsoft.Extensions.Logging.LogLevel.Trace,
LogLevel.Debug => Microsoft.Extensions.Logging.LogLevel.Debug,
LogLevel.Information => Microsoft.Extensions.Logging.LogLevel.Information,
LogLevel.Warning => Microsoft.Extensions.Logging.LogLevel.Warning,
LogLevel.Error => Microsoft.Extensions.Logging.LogLevel.Error,
_ => Microsoft.Extensions.Logging.LogLevel.Information
};
if (exception != null)
{
_logger.Log(msLogLevel, default, message, exception, (str, exc) => string.Format("{0} : {1}", str, exc));
}
/// <inheritdoc/>
public void Log(LogLevel level, string message, Exception? exception = null)
else
{
var msLogLevel = level switch
{
Telegrator.Logging.LogLevel.Trace => Microsoft.Extensions.Logging.LogLevel.Trace,
Telegrator.Logging.LogLevel.Debug => Microsoft.Extensions.Logging.LogLevel.Debug,
Telegrator.Logging.LogLevel.Information => Microsoft.Extensions.Logging.LogLevel.Information,
Telegrator.Logging.LogLevel.Warning => Microsoft.Extensions.Logging.LogLevel.Warning,
Telegrator.Logging.LogLevel.Error => Microsoft.Extensions.Logging.LogLevel.Error,
_ => Microsoft.Extensions.Logging.LogLevel.Information
};
if (exception != null)
{
_logger.Log(msLogLevel, default, message, exception, (str, exc) => string.Format("{0} : {1}", str, exc));
}
else
{
_logger.Log(msLogLevel, default, message, null, (str, _) => str);
}
_logger.Log(msLogLevel, default, message, null, (str, _) => str);
}
}
}
}
@@ -7,54 +7,53 @@ using Telegrator.Core;
using Telegrator.Core.States;
using Telegrator.Mediation;
namespace Telegrator.Polling
namespace Telegrator.Polling;
/// <inheritdoc/>
public class HostUpdateRouter : UpdateRouter
{
/// <summary>
/// <see cref="ILogger"/> of this router
/// </summary>
protected readonly ILogger<HostUpdateRouter> Logger;
/// <inheritdoc/>
public class HostUpdateRouter : UpdateRouter
public HostUpdateRouter(
IHandlersProvider handlersProvider,
IAwaitingProvider awaitingProvider,
IStateStorage stateStorage,
IOptions<TelegratorOptions> options,
ITelegramBotInfo botInfo,
ILogger<HostUpdateRouter> logger) : base(handlersProvider, awaitingProvider, stateStorage, options.Value, botInfo)
{
/// <summary>
/// <see cref="ILogger"/> of this router
/// </summary>
protected readonly ILogger<HostUpdateRouter> Logger;
Logger = logger;
ExceptionHandler = new DefaultRouterExceptionHandler(HandleException);
}
/// <inheritdoc/>
public HostUpdateRouter(
IHandlersProvider handlersProvider,
IAwaitingProvider awaitingProvider,
IStateStorage stateStorage,
IOptions<TelegratorOptions> options,
ITelegramBotInfo botInfo,
ILogger<HostUpdateRouter> logger) : base(handlersProvider, awaitingProvider, stateStorage, options.Value, botInfo)
/// <inheritdoc/>
public override Task HandleUpdateAsync(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken)
{
//Logger.LogInformation("Received update of type \"{type}\"", update.Type);
return base.HandleUpdateAsync(botClient, update, cancellationToken);
}
/// <summary>
/// Default exception handler of this router
/// </summary>
/// <param name="botClient"></param>
/// <param name="exception"></param>
/// <param name="source"></param>
/// <param name="cancellationToken"></param>
public void HandleException(ITelegramBotClient botClient, Exception exception, HandleErrorSource source, CancellationToken cancellationToken)
{
if (exception is HandlerFaultedException handlerFaultedException)
{
Logger = logger;
ExceptionHandler = new DefaultRouterExceptionHandler(HandleException);
Logger.LogError("\"{handler}\" handler's execution was faulted :\n{exception}",
handlerFaultedException.HandlerInfo.ToString(),
handlerFaultedException.InnerException?.ToString() ?? "No inner exception");
return;
}
/// <inheritdoc/>
public override Task HandleUpdateAsync(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken)
{
//Logger.LogInformation("Received update of type \"{type}\"", update.Type);
return base.HandleUpdateAsync(botClient, update, cancellationToken);
}
/// <summary>
/// Default exception handler of this router
/// </summary>
/// <param name="botClient"></param>
/// <param name="exception"></param>
/// <param name="source"></param>
/// <param name="cancellationToken"></param>
public void HandleException(ITelegramBotClient botClient, Exception exception, HandleErrorSource source, CancellationToken cancellationToken)
{
if (exception is HandlerFaultedException handlerFaultedException)
{
Logger.LogError("\"{handler}\" handler's execution was faulted :\n{exception}",
handlerFaultedException.HandlerInfo.ToString(),
handlerFaultedException.InnerException?.ToString() ?? "No inner exception");
return;
}
Logger.LogError("Exception was thrown during update routing faulted :\n{exception}", exception.ToString());
}
Logger.LogError("Exception was thrown during update routing faulted :\n{exception}", exception.ToString());
}
}
@@ -6,27 +6,26 @@ using Telegram.Bot.Polling;
using Telegrator.Core;
using Telegrator.Mediation;
namespace Telegrator.Polling
{
/// <summary>
/// Service for receiving updates for Hosted telegram bots
/// </summary>
/// <param name="botClient"></param>
/// <param name="updateRouter"></param>
/// <param name="options"></param>
/// <param name="logger"></param>
public class HostedUpdateReceiver(ITelegramBotClient botClient, IUpdateRouter updateRouter, IOptions<ReceiverOptions> options, ILogger<HostedUpdateReceiver> logger) : BackgroundService
{
private readonly ReceiverOptions _receiverOptions = options.Value;
private readonly IUpdateRouter _updateRouter = updateRouter;
namespace Telegrator.Polling;
/// <inheritdoc/>
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
logger.LogInformation("Starting receiving updates via long-polling");
_receiverOptions.AllowedUpdates = _updateRouter.HandlersProvider.AllowedTypes.ToArray();
DefaultUpdateReceiver updateReceiver = new DefaultUpdateReceiver(botClient, _receiverOptions);
await updateReceiver.ReceiveAsync(_updateRouter, stoppingToken).ConfigureAwait(false);
}
/// <summary>
/// Service for receiving updates for Hosted telegram bots
/// </summary>
/// <param name="botClient"></param>
/// <param name="updateRouter"></param>
/// <param name="options"></param>
/// <param name="logger"></param>
public class HostedUpdateReceiver(ITelegramBotClient botClient, IUpdateRouter updateRouter, IOptions<ReceiverOptions> options, ILogger<HostedUpdateReceiver> logger) : BackgroundService
{
private readonly ReceiverOptions _receiverOptions = options.Value;
private readonly IUpdateRouter _updateRouter = updateRouter;
/// <inheritdoc/>
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
logger.LogInformation("Starting receiving updates via long-polling");
_receiverOptions.AllowedUpdates = _updateRouter.HandlersProvider.AllowedTypes.ToArray();
DefaultUpdateReceiver updateReceiver = new DefaultUpdateReceiver(botClient, _receiverOptions);
await updateReceiver.ReceiveAsync(_updateRouter, stoppingToken).ConfigureAwait(false);
}
}
@@ -1,11 +1,9 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Options;
namespace Telegrator.Providers
namespace Telegrator.Providers;
/// <inheritdoc/>
public class HostAwaitingProvider(IOptions<TelegratorOptions> options) : AwaitingProvider(options.Value)
{
/// <inheritdoc/>
public class HostAwaitingProvider(IOptions<TelegratorOptions> options, ILogger<HostAwaitingProvider> logger) : AwaitingProvider(options.Value)
{
private readonly ILogger<HostAwaitingProvider> _logger = logger;
}
}
@@ -2,61 +2,60 @@
using Telegrator.Core;
using Telegrator.Core.Descriptors;
namespace Telegrator.Providers
namespace Telegrator.Providers;
/// <inheritdoc/>
public class HostHandlersCollection(IServiceCollection hostServiceColletion, TelegratorOptions options) : HandlersCollection(options)
{
private readonly IServiceCollection Services = hostServiceColletion;
/// <inheritdoc/>
public class HostHandlersCollection(IServiceCollection hostServiceColletion, TelegratorOptions options) : HandlersCollection(options)
protected override bool MustHaveParameterlessCtor => false;
/// <inheritdoc/>
public override IHandlersCollection AddDescriptor(HandlerDescriptor descriptor)
{
private readonly IServiceCollection Services = hostServiceColletion;
/// <inheritdoc/>
protected override bool MustHaveParameterlessCtor => false;
/// <inheritdoc/>
public override IHandlersCollection AddDescriptor(HandlerDescriptor descriptor)
switch (descriptor.Type)
{
switch (descriptor.Type)
{
case DescriptorType.General:
{
if (descriptor.InstanceFactory != null)
Services.AddScoped(descriptor.HandlerType, _ => descriptor.InstanceFactory.Invoke());
else
Services.AddScoped(descriptor.HandlerType);
case DescriptorType.General:
{
if (descriptor.InstanceFactory != null)
Services.AddScoped(descriptor.HandlerType, _ => descriptor.InstanceFactory.Invoke());
else
Services.AddScoped(descriptor.HandlerType);
break;
}
break;
}
case DescriptorType.Keyed:
{
if (descriptor.InstanceFactory != null)
Services.AddKeyedScoped(descriptor.HandlerType, descriptor.ServiceKey, (_, _) => descriptor.InstanceFactory.Invoke());
else
Services.AddKeyedScoped(descriptor.HandlerType, descriptor.ServiceKey);
case DescriptorType.Keyed:
{
if (descriptor.InstanceFactory != null)
Services.AddKeyedScoped(descriptor.HandlerType, descriptor.ServiceKey, (_, _) => descriptor.InstanceFactory.Invoke());
else
Services.AddKeyedScoped(descriptor.HandlerType, descriptor.ServiceKey);
break;
}
break;
}
case DescriptorType.Singleton:
{
Services.AddSingleton(descriptor.HandlerType, descriptor.SingletonInstance ?? (descriptor.InstanceFactory != null
? descriptor.InstanceFactory.Invoke()
: throw new Exception()));
case DescriptorType.Singleton:
{
Services.AddSingleton(descriptor.HandlerType, descriptor.SingletonInstance ?? (descriptor.InstanceFactory != null
? descriptor.InstanceFactory.Invoke()
: throw new Exception()));
break;
}
break;
}
case DescriptorType.Implicit:
{
Services.AddKeyedSingleton(descriptor.HandlerType, descriptor.ServiceKey, descriptor.SingletonInstance ?? (descriptor.InstanceFactory != null
? descriptor.InstanceFactory.Invoke()
: throw new Exception()));
break;
}
}
return base.AddDescriptor(descriptor);
case DescriptorType.Implicit:
{
Services.AddKeyedSingleton(descriptor.HandlerType, descriptor.ServiceKey, descriptor.SingletonInstance ?? (descriptor.InstanceFactory != null
? descriptor.InstanceFactory.Invoke()
: throw new Exception()));
break;
}
}
return base.AddDescriptor(descriptor);
}
}
@@ -1,45 +1,40 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Telegrator.Core;
using Telegrator.Core.Descriptors;
using Telegrator.Core.Handlers;
namespace Telegrator.Providers
namespace Telegrator.Providers;
/// <inheritdoc/>
public class HostHandlersProvider : HandlersProvider
{
private readonly IServiceProvider Services;
/// <inheritdoc/>
public class HostHandlersProvider : HandlersProvider
public HostHandlersProvider(
IHandlersCollection handlers,
IOptions<TelegratorOptions> options,
IServiceProvider serviceProvider) : base(handlers, options.Value)
{
private readonly IServiceProvider Services;
private readonly ILogger<HostHandlersProvider> Logger;
Services = serviceProvider;
}
/// <inheritdoc/>
public HostHandlersProvider(
IHandlersCollection handlers,
IOptions<TelegratorOptions> options,
IServiceProvider serviceProvider,
ILogger<HostHandlersProvider> logger) : base(handlers, options.Value)
{
Services = serviceProvider;
Logger = logger;
}
/// <inheritdoc/>
public override UpdateHandlerBase GetHandlerInstance(HandlerDescriptor descriptor, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
IServiceScope scope = Services.CreateScope();
/// <inheritdoc/>
public override UpdateHandlerBase GetHandlerInstance(HandlerDescriptor descriptor, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
IServiceScope scope = Services.CreateScope();
object handlerInstance = descriptor.ServiceKey == null
? scope.ServiceProvider.GetRequiredService(descriptor.HandlerType)
: scope.ServiceProvider.GetRequiredKeyedService(descriptor.HandlerType, descriptor.ServiceKey);
object handlerInstance = descriptor.ServiceKey == null
? scope.ServiceProvider.GetRequiredService(descriptor.HandlerType)
: scope.ServiceProvider.GetRequiredKeyedService(descriptor.HandlerType, descriptor.ServiceKey);
if (handlerInstance is not UpdateHandlerBase updateHandler)
throw new InvalidOperationException("Failed to resolve " + descriptor.HandlerType + " as UpdateHandlerBase");
if (handlerInstance is not UpdateHandlerBase updateHandler)
throw new InvalidOperationException("Failed to resolve " + descriptor.HandlerType + " as UpdateHandlerBase");
descriptor.LazyInitialization?.Invoke(updateHandler);
updateHandler.LifetimeToken.OnLifetimeEnded += _ => scope.Dispose();
return updateHandler;
}
descriptor.LazyInitialization?.Invoke(updateHandler);
updateHandler.LifetimeToken.OnLifetimeEnded += _ => scope.Dispose();
return updateHandler;
}
}