Добавьте файлы проекта.

This commit is contained in:
2025-07-24 23:19:59 +04:00
commit 33d1f6218a
168 changed files with 15035 additions and 0 deletions
@@ -0,0 +1,15 @@
namespace Telegrator.Hosting.Components
{
/// <summary>
/// Interface for pre-building routines that can be executed during host construction.
/// Allows for custom initialization and configuration steps before the bot host is built.
/// </summary>
public interface IPreBuildingRoutine
{
/// <summary>
/// Executes the pre-building routine on the specified host builder.
/// </summary>
/// <param name="hostBuilder">The host builder to configure.</param>
public static abstract void PreBuildingRoutine(TelegramBotHostBuilder hostBuilder);
}
}
@@ -0,0 +1,14 @@
using Microsoft.Extensions.Hosting;
using Telegrator;
namespace Telegrator.Hosting.Components
{
/// <summary>
/// Interface for Telegram bot hosts.
/// Combines host application capabilities with reactive Telegram bot functionality.
/// </summary>
public interface ITelegramBotHost : IHost, IReactiveTelegramBot
{
}
}
@@ -0,0 +1,29 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Telegrator.MadiatorCore;
namespace Telegrator.Hosting.Components
{
/// <summary>
/// Interface for building Telegram bot hosts with dependency injection support.
/// Combines host application building capabilities with handler collection functionality.
/// </summary>
public interface ITelegramBotHostBuilder : ICollectingProvider
{
/// <summary>
/// Gets the set of key/value configuration properties.
/// </summary>
IConfigurationManager Configuration { get; }
/// <summary>
/// Gets a collection of logging providers for the application to compose. This is useful for adding new logging providers.
/// </summary>
ILoggingBuilder Logging { get; }
/// <summary>
/// Gets a collection of services for the application to compose. This is useful for adding user provided or framework provided services.
/// </summary>
IServiceCollection Services { get; }
}
}
@@ -0,0 +1,53 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace Telegrator.Hosting.Configuration
{
/// <summary>
/// Abstract base class for configuring options from configuration sources.
/// Provides a proxy pattern for binding configuration to strongly-typed options classes.
/// </summary>
/// <typeparam name="TOptions">The type of options to configure.</typeparam>
public abstract class ConfigureOptionsProxy<TOptions> where TOptions : class
{
/// <summary>
/// Configures the options using the default configuration section.
/// </summary>
/// <param name="services">The service collection to configure.</param>
/// <param name="configuration">The configuration source.</param>
public void Configure(IServiceCollection services, IConfiguration configuration)
=> Configure(services, Options.DefaultName, configuration, null);
/// <summary>
/// Configures the options using a named configuration section.
/// </summary>
/// <param name="services">The service collection to configure.</param>
/// <param name="name">The name of the configuration section.</param>
/// <param name="configuration">The configuration source.</param>
public void Configure(IServiceCollection services, string? name, IConfiguration configuration)
=> Configure(services, name, configuration, null);
/// <summary>
/// Configures the options using a named configuration section with custom binder options.
/// </summary>
/// <param name="services">The service collection to configure.</param>
/// <param name="name">The name of the configuration section.</param>
/// <param name="configuration">The configuration source.</param>
/// <param name="configureBinder">Optional action to configure the binder options.</param>
public void Configure(IServiceCollection services, string? name, IConfiguration configuration, Action<BinderOptions>? configureBinder)
{
var namedConfigure = new NamedConfigureFromConfigurationOptions<ConfigureOptionsProxy<TOptions>>(name, configuration, configureBinder);
namedConfigure.Configure(name, this);
services.AddOptions();
services.AddSingleton(Options.Create(Realize()));
}
/// <summary>
/// Creates the actual options instance from the configuration.
/// </summary>
/// <returns>The configured options instance.</returns>
protected abstract TOptions Realize();
}
}
@@ -0,0 +1,46 @@
using Telegram.Bot;
namespace Telegrator.Hosting.Configuration
{
/// <summary>
/// Internal proxy class for configuring Telegram bot client options from configuration.
/// Extends ConfigureOptionsProxy to provide specific configuration for Telegram bot client options.
/// </summary>
internal class TelegramBotClientOptionsProxy : ConfigureOptionsProxy<TelegramBotClientOptions>
{
/// <summary>
/// Gets or sets the bot token.
/// </summary>
public string Token { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the base URL for the bot API.
/// </summary>
public string? BaseUrl { get; set; } = null;
/// <summary>
/// Gets or sets whether to use the test environment.
/// </summary>
public bool UseTestEnvironment { get; set; } = false;
/// <summary>
/// Gets or sets the retry threshold in seconds.
/// </summary>
public int RetryThreshold { get; set; } = 60;
/// <summary>
/// Gets or sets the number of retry attempts.
/// </summary>
public int RetryCount { get; set; } = 3;
/// <summary>
/// Creates a TelegramBotClientOptions instance from the proxy configuration.
/// </summary>
/// <returns>The configured TelegramBotClientOptions instance.</returns>
protected override TelegramBotClientOptions Realize() => new TelegramBotClientOptions(Token, BaseUrl, UseTestEnvironment)
{
RetryCount = RetryCount,
RetryThreshold = RetryThreshold
};
}
}
+8
View File
@@ -0,0 +1,8 @@
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.
using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("Style", "IDE0290")]
@@ -0,0 +1,20 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Telegrator.Configuration;
using Telegrator.MadiatorCore.Descriptors;
using Telegrator.Polling;
namespace Telegrator.Hosting.Polling
{
public class HostUpdateHandlersPool(IOptions<TelegramBotOptions> options, ILogger<HostUpdateHandlersPool> logger)
: UpdateHandlersPool(options.Value, options.Value.GlobalCancellationToken)
{
private readonly ILogger<HostUpdateHandlersPool> _logger = logger;
protected override async Task ExecuteHandlerWrapper(DescribedHandlerInfo enqueuedHandler)
{
_logger.LogInformation("Handler \"{0}\" has entered execution pool", enqueuedHandler.DisplayString);
await base.ExecuteHandlerWrapper(enqueuedHandler);
}
}
}
@@ -0,0 +1,46 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Telegram.Bot;
using Telegram.Bot.Polling;
using Telegram.Bot.Types;
using Telegrator;
using Telegrator.Configuration;
using Telegrator.MadiatorCore;
using Telegrator.Polling;
namespace Telegrator.Hosting.Polling
{
public class HostUpdateRouter : UpdateRouter
{
protected readonly ILogger<HostUpdateRouter> Logger;
public HostUpdateRouter(IHandlersProvider handlersProvider, IAwaitingProvider awaitingProvider, IOptions<TelegramBotOptions> options, IUpdateHandlersPool handlersPool, ILogger<HostUpdateRouter> logger)
: base(handlersProvider, awaitingProvider, options.Value, handlersPool)
{
Logger = logger;
ExceptionHandler = new HostExceptionHandler(logger);
}
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);
}
private class HostExceptionHandler(ILogger<HostUpdateRouter> logger) : IRouterExceptionHandler
{
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.DisplayString,
handlerFaultedException.InnerException?.ToString() ?? "No inner exception");
return;
}
logger.LogError("Exception was thrown during update routing faulted :\n{exception}", exception.ToString());
}
}
}
}
@@ -0,0 +1,25 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Telegram.Bot;
using Telegram.Bot.Polling;
using Telegrator.Hosting.Components;
using Telegrator.MadiatorCore;
using Telegrator.Polling;
namespace Telegrator.Hosting.Polling
{
public class HostedUpdateReceiver(ITelegramBotHost botHost, ITelegramBotClient botClient, IUpdateRouter updateRouter, IOptions<ReceiverOptions> options, ILogger<HostedUpdateReceiver> logger) : BackgroundService
{
private readonly ReceiverOptions ReceiverOptions = options.Value;
private readonly IUpdateRouter UpdateRouter = updateRouter;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
logger.LogInformation("Starting receiving updates via long-polling");
ReceiverOptions.AllowedUpdates = botHost.UpdateRouter.HandlersProvider.AllowedTypes.ToArray();
ReactiveUpdateReceiver updateReceiver = new ReactiveUpdateReceiver(botClient, ReceiverOptions);
await updateReceiver.ReceiveAsync(UpdateRouter, stoppingToken).ConfigureAwait(false);
}
}
}
@@ -0,0 +1,21 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Telegram.Bot;
using Telegram.Bot.Types;
using Telegrator.Configuration;
using Telegrator.MadiatorCore;
using Telegrator.MadiatorCore.Descriptors;
using Telegrator.Providers;
namespace Telegrator.Hosting.Providers
{
public class HostAwaitingProvider(IOptions<TelegramBotOptions> options, ITelegramBotInfo botInfo, ILogger<HostAwaitingProvider> logger) : AwaitingProvider(options.Value, botInfo)
{
public override IEnumerable<DescribedHandlerInfo> GetHandlers(IUpdateRouter updateRouter, ITelegramBotClient client, Update update, CancellationToken cancellationToken = default)
{
IEnumerable<DescribedHandlerInfo> handlers = base.GetHandlers(updateRouter, client, update, cancellationToken).ToArray();
logger.LogInformation("Described awaiting handlers : {handlers}", string.Join(", ", handlers.Select(hndlr => hndlr.HandlerInstance.GetType().Name)));
return handlers;
}
}
}
@@ -0,0 +1,79 @@
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;
using Telegrator.Configuration;
using Telegrator.Hosting.Components;
using Telegrator.MadiatorCore;
using Telegrator.MadiatorCore.Descriptors;
using Telegrator.Providers;
namespace Telegrator.Hosting.Providers
{
public class HostHandlersCollection(IServiceCollection hostServiceColletion, IHandlersCollectingOptions options) : HandlersCollection(options)
{
private readonly IServiceCollection Services = hostServiceColletion;
public readonly List<Action<TelegramBotHostBuilder>> PreBuilderRoutines = [];
protected override bool MustHaveParameterlessCtor => false;
public override IHandlersCollection AddHandler(Type handlerType)
{
//
if (handlerType.GetInterface(nameof(IPreBuildingRoutine)) != null)
{
MethodInfo? methodInfo = handlerType.GetMethod(nameof(IPreBuildingRoutine.PreBuildingRoutine), BindingFlags.Static | BindingFlags.Public);
if (methodInfo != null)
{
Action<TelegramBotHostBuilder> routineDelegate = methodInfo.CreateDelegate<Action<TelegramBotHostBuilder>>(null);
PreBuilderRoutines.Add(routineDelegate);
}
}
return base.AddHandler(handlerType);
}
public override IHandlersCollection AddDescriptor(HandlerDescriptor descriptor)
{
switch (descriptor.Type)
{
case DescriptorType.General:
{
if (descriptor.InstanceFactory != null)
Services.AddScoped(descriptor.HandlerType, _ => descriptor.InstanceFactory.Invoke());
else
Services.AddScoped(descriptor.HandlerType);
break;
}
case DescriptorType.Keyed:
{
if (descriptor.InstanceFactory != null)
Services.AddKeyedScoped(descriptor.HandlerType, descriptor.ServiceKey, (_, _) => descriptor.InstanceFactory.Invoke());
else
Services.AddKeyedScoped(descriptor.HandlerType, descriptor.ServiceKey);
break;
}
case DescriptorType.Singleton:
{
Services.AddSingleton(descriptor.HandlerType, descriptor.SingletonInstance ?? (descriptor.InstanceFactory != null
? descriptor.InstanceFactory.Invoke()
: throw new Exception()));
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);
}
}
}
@@ -0,0 +1,48 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Telegram.Bot;
using Telegram.Bot.Types;
using Telegrator.Configuration;
using Telegrator.Handlers.Components;
using Telegrator.MadiatorCore;
using Telegrator.MadiatorCore.Descriptors;
using Telegrator.Providers;
namespace Telegrator.Hosting.Providers
{
public class HostHandlersProvider : HandlersProvider
{
private readonly IServiceProvider Services;
private readonly ILogger<HostHandlersProvider> Logger;
public HostHandlersProvider(IHandlersCollection handlers, IOptions<TelegramBotOptions> options, ITelegramBotInfo botInfo, IServiceProvider serviceProvider, ILogger<HostHandlersProvider> logger)
: base(handlers, options.Value, botInfo)
{
Services = serviceProvider;
Logger = logger;
}
public override IEnumerable<DescribedHandlerInfo> GetHandlers(IUpdateRouter updateRouter, ITelegramBotClient client, Update update, CancellationToken cancellationToken = default)
{
IEnumerable<DescribedHandlerInfo> handlers = base.GetHandlers(updateRouter, client, update, cancellationToken).ToArray();
Logger.LogInformation("Described handlers : {handlers}", string.Join(", ", handlers.Select(hndlr => hndlr.DisplayString ?? hndlr.HandlerInstance.GetType().Name)));
return handlers;
}
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);
if (handlerInstance is not UpdateHandlerBase updateHandler)
throw new InvalidOperationException();
updateHandler.LifetimeToken.OnLifetimeEnded += _ => scope.Dispose();
return updateHandler;
}
}
}
+118
View File
@@ -0,0 +1,118 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Text;
using Telegram.Bot.Types.Enums;
using Telegrator.Hosting.Components;
using Telegrator.Hosting.Providers;
using Telegrator.MadiatorCore;
using Telegrator.MadiatorCore.Descriptors;
namespace Telegrator.Hosting
{
public class TelegramBotHost : ITelegramBotHost
{
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>
/// This application's logger
/// </summary>
public ILogger<TelegramBotHost> Logger => _logger;
/// <summary>
/// Initializes a new instance of the <see cref="TelegramBotHost"/> class.
/// </summary>
/// <param name="serviceProvider">The service provider.</param>
internal TelegramBotHost(HostApplicationBuilder hostApplicationBuilder, HostHandlersCollection handlers)
{
RegisterHostServices(hostApplicationBuilder, handlers);
_innerHost = hostApplicationBuilder.Build();
_updateRouter = Services.GetRequiredService<IUpdateRouter>();
_logger = Services.GetRequiredService<ILogger<TelegramBotHost>>();
LogHandlers(handlers);
}
public static TelegramBotHostBuilder CreateBuilder()
{
TelegramBotHostBuilder builder = new TelegramBotHostBuilder(null);
builder.Services.AddTelegramBotHostDefaults();
builder.Services.AddTelegramReceiver();
return builder;
}
public static TelegramBotHostBuilder CreateBuilder(TelegramBotHostBuilderSettings? settings)
{
TelegramBotHostBuilder builder = new TelegramBotHostBuilder(settings);
builder.Services.AddTelegramBotHostDefaults();
builder.Services.AddTelegramReceiver();
return builder;
}
/// <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;
GC.SuppressFinalize(this);
_disposed = true;
}
private void LogHandlers(HostHandlersCollection 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.AppendLine("\n\tUpdateType." + updateType + " :");
foreach (HandlerDescriptor descriptor in descriptors.Reverse())
{
string indexerString = descriptor.Indexer.ToString();
logBuilder.AppendLine("* " + indexerString + " " + (descriptor.DisplayString ?? descriptor.HandlerType.Name));
}
}
Logger.LogInformation(logBuilder.ToString());
}
private void RegisterHostServices(HostApplicationBuilder hostApplicationBuilder, HostHandlersCollection handlers)
{
//hostApplicationBuilder.Services.RemoveAll<IHost>();
//hostApplicationBuilder.Services.AddSingleton<IHost>(this);
hostApplicationBuilder.Services.AddSingleton<ITelegramBotHost>(this);
hostApplicationBuilder.Services.AddSingleton<IReactiveTelegramBot>(this);
hostApplicationBuilder.Services.AddSingleton<IHandlersCollection>(handlers);
}
}
}
@@ -0,0 +1,73 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Telegram.Bot;
using Telegram.Bot.Polling;
using Telegrator.Hosting.Configuration;
using Telegrator.Configuration;
using Telegrator.Hosting;
using Telegrator.Hosting.Components;
using Telegrator.Hosting.Providers;
using Telegrator.MadiatorCore;
#pragma warning disable IDE0001
namespace Telegrator.Hosting
{
public class TelegramBotHostBuilder : ITelegramBotHostBuilder
{
private readonly HostApplicationBuilder _innerBuilder;
private readonly TelegramBotHostBuilderSettings _settings;
private readonly HostHandlersCollection _handlers;
/// <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;
/// <summary>
/// Initializes a new instance of the <see cref="TelegramBotHostBuilder"/> class.
/// </summary>
internal TelegramBotHostBuilder(TelegramBotHostBuilderSettings? settings = null)
{
_settings = settings ?? new TelegramBotHostBuilderSettings();
_innerBuilder = new HostApplicationBuilder(settings?.ToApplicationBuilderSettings());
_handlers = new HostHandlersCollection(Services, _settings);
Services.Configure<TelegramBotOptions>(Configuration.GetSection(nameof(TelegramBotOptions)));
Services.Configure<ReceiverOptions>(Configuration.GetSection(nameof(ReceiverOptions)));
Services.Configure<TelegramBotClientOptions>(Configuration.GetSection(nameof(TelegramBotClientOptions)), new TelegramBotClientOptionsProxy());
}
/// <summary>
/// Builds the host.
/// </summary>
/// <returns></returns>
public TelegramBotHost Build()
{
foreach (var preBuildRoutine in _handlers.PreBuilderRoutines)
{
try
{
preBuildRoutine.Invoke(this);
}
catch (NotImplementedException)
{
_ = 0xBAD + 0xC0DE;
}
}
return new TelegramBotHost(_innerBuilder, _handlers);
}
}
}
@@ -0,0 +1,46 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Telegrator.Configuration;
namespace Telegrator.Hosting
{
/// <summary>
///
/// </summary>
public class TelegramBotHostBuilderSettings() : IHandlersCollectingOptions
{
/// <inheritdoc cref="HostApplicationBuilderSettings.DisableDefaults"/>
public bool DisableDefaults { get; set; }
/// <inheritdoc cref="HostApplicationBuilderSettings.Args"/>
public string[]? Args { get; set; }
/// <inheritdoc cref="HostApplicationBuilderSettings.Configuration"/>
public ConfigurationManager? Configuration { get; set; }
/// <inheritdoc cref="HostApplicationBuilderSettings.EnvironmentName"/>
public string? EnvironmentName { get; set; }
/// <inheritdoc cref="HostApplicationBuilderSettings.ApplicationName"/>
public string? ApplicationName { get; set; }
/// <inheritdoc cref="HostApplicationBuilderSettings.ContentRootPath"/>
public string? ContentRootPath { get; set; }
/// <inheritdoc/>
public bool DescendDescriptorIndex { get; set; } = true;
/// <inheritdoc/>
public bool ExceptIntersectingCommandAliases { get; set; } = true;
internal HostApplicationBuilderSettings ToApplicationBuilderSettings() => new HostApplicationBuilderSettings()
{
DisableDefaults = DisableDefaults,
Args = Args,
Configuration = Configuration,
EnvironmentName = EnvironmentName,
ApplicationName = ApplicationName,
ContentRootPath = ContentRootPath
};
}
}
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Configurations>Debug;Release</Configurations>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.5" />
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Telegrator\Telegrator.csproj" />
</ItemGroup>
</Project>
+58
View File
@@ -0,0 +1,58 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Telegram.Bot;
using Telegram.Bot.Types;
using Telegrator;
using Telegrator.Configuration;
using Telegrator.Hosting.Components;
using Telegrator.Hosting.Configuration;
using Telegrator.Hosting.Polling;
using Telegrator.Hosting.Providers;
using Telegrator.MadiatorCore;
namespace Telegrator.Hosting
{
public static class ServicesCollectionExtensions
{
public static IServiceCollection Configure<TOptions>(this IServiceCollection services, IConfiguration configuration, ConfigureOptionsProxy<TOptions> optionsProxy) where TOptions : class
{
optionsProxy.Configure(services, configuration);
return services;
}
public static IServiceCollection AddTelegramBotHostDefaults(this IServiceCollection services)
{
services.AddLogging(builder => builder.AddConsole());
services.AddSingleton<IUpdateHandlersPool, HostUpdateHandlersPool>();
services.AddSingleton<IAwaitingProvider, HostAwaitingProvider>();
services.AddSingleton<IHandlersProvider, HostHandlersProvider>();
services.AddSingleton<IUpdateRouter, HostUpdateRouter>();
services.AddSingleton<ITelegramBotInfo, TelegramBotInfo>(services => new TelegramBotInfo(services.GetRequiredService<ITelegramBotClient>().GetMe().Result));
return services;
}
public static IServiceCollection AddTelegramReceiver(this IServiceCollection services)
{
services.AddHttpClient<ITelegramBotClient>("tgreceiver").RemoveAllLoggers().AddTypedClient(TypedTelegramBotClientFactory);
services.AddHostedService<HostedUpdateReceiver>();
return services;
}
private static ITelegramBotClient TypedTelegramBotClientFactory(HttpClient httpClient, IServiceProvider provider)
=> new TelegramBotClient(provider.GetRequiredService<IOptions<TelegramBotClientOptions>>().Value, httpClient);
}
public static class TelegramBotHostExtensions
{
public static ITelegramBotHost SetBotCommands(this ITelegramBotHost botHost)
{
ITelegramBotClient client = botHost.Services.GetRequiredService<ITelegramBotClient>();
IEnumerable<BotCommand> aliases = botHost.UpdateRouter.HandlersProvider.GetBotCommands();
client.SetMyCommands(aliases).Wait();
return botHost;
}
}
}