diff --git a/Telegrator.ConsoleHost.Web/Program.cs b/Telegrator.ConsoleHost.Web/Program.cs
new file mode 100644
index 0000000..3b67d23
--- /dev/null
+++ b/Telegrator.ConsoleHost.Web/Program.cs
@@ -0,0 +1,25 @@
+using Telegrator.Hosting;
+using Telegrator.Hosting.Web;
+
+namespace Telegrator.ConsoleHost.Web
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ TelegramBotWebHostBuilder builder = TelegramBotWebHost.CreateBuilder(new TelegramBotWebOptions()
+ {
+ Args = args,
+ WebhookUri = "https://telegrator-hooker.cloudpub.ru/bot",
+ DescendDescriptorIndex = false,
+ ExceptIntersectingCommandAliases = true,
+ });
+
+ builder.Handlers.CollectHandlersAssemblyWide();
+
+ TelegramBotWebHost telegramBot = builder.Build();
+ telegramBot.SetBotCommands();
+ telegramBot.Run();
+ }
+ }
+}
diff --git a/Telegrator.ConsoleHost.Web/Properties/launchSettings.json b/Telegrator.ConsoleHost.Web/Properties/launchSettings.json
new file mode 100644
index 0000000..f4d95e9
--- /dev/null
+++ b/Telegrator.ConsoleHost.Web/Properties/launchSettings.json
@@ -0,0 +1,38 @@
+{
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "dotnetRunMessages": true,
+ "applicationUrl": "http://localhost:5284"
+ },
+ "https": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "dotnetRunMessages": true,
+ "applicationUrl": "https://localhost:8080"
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ },
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:12266",
+ "sslPort": 44308
+ }
+ }
+}
\ No newline at end of file
diff --git a/Telegrator.ConsoleHost.Web/Telegrator.ConsoleHost.Web.csproj b/Telegrator.ConsoleHost.Web/Telegrator.ConsoleHost.Web.csproj
new file mode 100644
index 0000000..fd9af14
--- /dev/null
+++ b/Telegrator.ConsoleHost.Web/Telegrator.ConsoleHost.Web.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/Telegrator.ConsoleHost.Web/appsettings.Development.json b/Telegrator.ConsoleHost.Web/appsettings.Development.json
new file mode 100644
index 0000000..0c208ae
--- /dev/null
+++ b/Telegrator.ConsoleHost.Web/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/Telegrator.ConsoleHost.Web/appsettings.json b/Telegrator.ConsoleHost.Web/appsettings.json
new file mode 100644
index 0000000..e1dc924
--- /dev/null
+++ b/Telegrator.ConsoleHost.Web/appsettings.json
@@ -0,0 +1,28 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+
+ "TelegramBotClientOptions": {
+ "Token": "7625502724:AAE5QPuX5P_lk2HwV4kdE6guoM6nsFQbe-c"
+ },
+
+ "TelegramBotOptions": {
+ "ExecuteOnlyFirstFoundHanlder": true,
+ "MaximumParallelWorkingHandlers": null
+ },
+
+ "HostOptions": {
+ "ShutdownTimeout": 10,
+ "BackgroundServiceExceptionBehavior": "StopHost"
+ },
+
+ "Shapes": {
+ "Token": "AX5IHZHSZMGQVEC6TILCOFLALPQRDDUWEBT8UYPH0OW"
+ },
+
+ "AllowedHosts": "*"
+}
\ No newline at end of file
diff --git a/Telegrator.Generators/ApiMarkdownGenerator.cs b/Telegrator.Generators/ApiMarkdownGenerator.cs
index 9b1f7e5..261a6b3 100644
--- a/Telegrator.Generators/ApiMarkdownGenerator.cs
+++ b/Telegrator.Generators/ApiMarkdownGenerator.cs
@@ -4,6 +4,7 @@ using System.Collections.Immutable;
using System.Text;
using System.Xml.Linq;
+#pragma warning disable CS0162
namespace Telegrator.Generators
{
///
@@ -14,6 +15,11 @@ namespace Telegrator.Generators
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
+#if RELEASE
+ // DEBUG ONLY GENERATOR
+ return;
+#endif
+
IncrementalValueProvider> typeDeclarations = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: (node, _) => node is ClassDeclarationSyntax || node is InterfaceDeclarationSyntax || node is StructDeclarationSyntax || node is EnumDeclarationSyntax,
diff --git a/Telegrator.Hosting.Web/Components/ITelegramBotWebHost.cs b/Telegrator.Hosting.Web/Components/ITelegramBotWebHost.cs
index 5ab2dc0..aa286c6 100644
--- a/Telegrator.Hosting.Web/Components/ITelegramBotWebHost.cs
+++ b/Telegrator.Hosting.Web/Components/ITelegramBotWebHost.cs
@@ -1,8 +1,14 @@
-using Telegrator.Hosting.Components;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Routing;
+using Telegrator.Hosting.Components;
namespace Telegrator.Hosting.Web.Components
{
- public interface ITelegramBotWebHost : ITelegramBotHost//, IEndpointRouteBuilder
+ ///
+ /// Interface for Telegram bot hosts with Webhook update receiving.
+ /// Combines wbe application capabilities with reactive Telegram bot functionality.
+ ///
+ public interface ITelegramBotWebHost : ITelegramBotHost, IEndpointRouteBuilder, IApplicationBuilder, IAsyncDisposable
{
}
diff --git a/Telegrator.Hosting.Web/GlobalSuppressions.cs b/Telegrator.Hosting.Web/GlobalSuppressions.cs
new file mode 100644
index 0000000..e8cd1b7
--- /dev/null
+++ b/Telegrator.Hosting.Web/GlobalSuppressions.cs
@@ -0,0 +1,10 @@
+// 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")]
+[assembly: SuppressMessage("Style", "IDE0090")]
+[assembly: SuppressMessage("Usage", "CA2254")]
diff --git a/Telegrator.Hosting.Web/Polling/HostedUpdateWebhooker.cs b/Telegrator.Hosting.Web/Polling/HostedUpdateWebhooker.cs
index 36cd5e7..b2cccf6 100644
--- a/Telegrator.Hosting.Web/Polling/HostedUpdateWebhooker.cs
+++ b/Telegrator.Hosting.Web/Polling/HostedUpdateWebhooker.cs
@@ -1,49 +1,93 @@
-using Microsoft.Extensions.Hosting;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+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
{
+ ///
+ /// Service for receiving updates for Hosted telegram bots via Webhooks
+ ///
public class HostedUpdateWebhooker : IHostedService
{
+ private const string SecretTokenHeader = "X-Telegram-Bot-Api-Secret-Token";
+
private readonly ITelegramBotWebHost _botHost;
private readonly ITelegramBotClient _botClient;
private readonly IUpdateRouter _updateRouter;
private readonly TelegramBotWebOptions _options;
+ ///
+ /// Initiallizes new instance of
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public HostedUpdateWebhooker(ITelegramBotWebHost 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");
- if (string.IsNullOrEmpty(options.Value.WebhookPattern))
- throw new ArgumentNullException(nameof(options), "Option \"WebhookPattern\" must be set to subscribe for update recieving");
-
_botHost = botHost;
_botClient = botClient;
_updateRouter = updateRouter;
_options = options.Value;
}
+ ///
public Task StartAsync(CancellationToken cancellationToken)
{
+ string pattern = new UriBuilder(_options.WebhookUri).Path;
+ _botHost.MapPost(pattern, (Delegate)ReceiveUpdate);
+
_botClient.SetWebhook(
url: _options.WebhookUri,
maxConnections: _options.MaxConnections,
allowedUpdates: _botHost.UpdateRouter.HandlersProvider.AllowedTypes,
dropPendingUpdates: _options.DropPendingUpdates,
- cancellationToken: cancellationToken);
+ cancellationToken: cancellationToken)
+ .Wait(cancellationToken);
- //botHost.MapGet(_options.WebhookPattern, async (Update update) => await _updateRouter.HandleUpdateAsync(_botClient, update, cancellationToken));
return Task.CompletedTask;
}
+ ///
public Task StopAsync(CancellationToken cancellationToken)
{
_botClient.DeleteWebhook(_options.DropPendingUpdates, cancellationToken);
return Task.CompletedTask;
}
+
+ private async Task ReceiveUpdate(HttpContext ctx)
+ {
+ if (_options.SecretToken != null)
+ {
+ if (!ctx.Request.Headers.TryGetValue(SecretTokenHeader, out StringValues strings))
+ return Results.BadRequest();
+
+ string? secret = strings.SingleOrDefault();
+ if (secret == null)
+ return Results.BadRequest();
+
+ if (_options.SecretToken != secret)
+ return Results.StatusCode(401);
+ }
+
+ Update? update = await JsonSerializer.DeserializeAsync(ctx.Request.Body, JsonBotAPI.Options, ctx.RequestAborted);
+ if (update is not { Id: > 0 })
+ return Results.BadRequest();
+
+ await _updateRouter.HandleUpdateAsync(_botClient, update, ctx.RequestAborted);
+ return Results.Ok();
+ }
}
}
diff --git a/Telegrator.Hosting.Web/README.md b/Telegrator.Hosting.Web/README.md
new file mode 100644
index 0000000..3635afa
--- /dev/null
+++ b/Telegrator.Hosting.Web/README.md
@@ -0,0 +1,84 @@
+# Telegrator.Hosting.Web
+
+**Telegrator.Hosting.Web** is an extension for the Telegrator framework that enables seamless integration with ASP.NET Core and webhook-based Telegram bots. It is designed for scalable, production-ready web applications.
+
+---
+
+## Features
+- ASP.NET Core integration for webhook-based bots
+- Automatic handler discovery and registration
+- Strongly-typed configuration via `appsettings.json` and environment variables
+- Dependency injection and middleware support
+- Graceful startup/shutdown and lifecycle management
+- Advanced error handling and logging
+- Supports all Telegrator handler/filter/state features
+
+---
+
+## Requirements
+- .NET 8.0 or later
+- ASP.NET Core
+
+---
+
+## Installation
+
+```shell
+dotnet add package Telegrator.Hosting.Web
+```
+
+---
+
+## Quick Start Example
+
+**Program.cs (ASP.NET Core):**
+```csharp
+using Telegrator.Hosting;
+using Telegrator.Hosting.Web;
+
+// Creating builder
+TelegramBotWebHostBuilder builder = TelegramBotWebHost.CreateBuilder(new TelegramBotWebOptions()
+{
+ Args = args,
+ WebhookUri = "https://you-public-host.ru/bot"
+ ExceptIntersectingCommandAliases = true
+});
+
+// Register handlers
+builder.Handlers.CollectHandlersAssemblyWide();
+builder.Services.AddHandlersFromAssembly(typeof(Program).Assembly);
+
+// Register your services
+builder.Services.AddSingleton();
+
+// Building and running application
+TelegramBotWebHost telegramBot = builder.Build();
+telegramBot.SetBotCommands();
+telegramBot.Run();
+```
+
+---
+
+## Configuration (appsettings.json)
+
+```json
+{
+ "TelegramBotClientOptions": {
+ "Token": "YOUR_BOT_TOKEN"
+ }
+}
+```
+
+- `TelegramBotClientOptions`: Bot token and client settings
+
+---
+
+## Documentation
+- [Telegrator Main Docs](https://github.com/Rikitav/Telegrator)
+- [Getting Started Guide](https://github.com/Rikitav/Telegrator/wiki/Getting-started)
+- [Annotation Overview](https://github.com/Rikitav/Telegrator/wiki/Annotation-overview)
+
+---
+
+## License
+GPLv3
\ No newline at end of file
diff --git a/Telegrator.Hosting.Web/TelegramBotWebHost.cs b/Telegrator.Hosting.Web/TelegramBotWebHost.cs
index 8e4dc29..5686ea4 100644
--- a/Telegrator.Hosting.Web/TelegramBotWebHost.cs
+++ b/Telegrator.Hosting.Web/TelegramBotWebHost.cs
@@ -1,10 +1,196 @@
-using Telegrator.Hosting.Components;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Routing;
+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.Hosting.Web.Components;
+using Telegrator.MadiatorCore;
+using Telegrator.MadiatorCore.Descriptors;
namespace Telegrator.Hosting.Web
{
- public class TelegramBotWebHost //: ITelegramBotWebHost
+ ///
+ /// 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;
+
+ internal TelegramBotWebHost(WebApplicationBuilder webApplicationBuilder, HostHandlersCollection handlers)
+ {
+ RegisterHostServices(webApplicationBuilder, handlers);
+ _innerApp = webApplicationBuilder.Build();
+
+ _updateRouter = Services.GetRequiredService();
+ _logger = Services.GetRequiredService>();
+
+ LogHandlers(handlers);
+ }
+
+ ///
+ /// 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 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.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(WebApplicationBuilder hostApplicationBuilder, HostHandlersCollection handlers)
+ {
+ //hostApplicationBuilder.Services.RemoveAll();
+ //hostApplicationBuilder.Services.AddSingleton(this);
+
+ hostApplicationBuilder.Services.AddSingleton(this);
+ hostApplicationBuilder.Services.AddSingleton(this);
+ hostApplicationBuilder.Services.AddSingleton(this);
+ hostApplicationBuilder.Services.AddSingleton(handlers);
+ }
}
}
diff --git a/Telegrator.Hosting.Web/TelegramBotWebHostBuilder.cs b/Telegrator.Hosting.Web/TelegramBotWebHostBuilder.cs
index 96b1202..cab6f3d 100644
--- a/Telegrator.Hosting.Web/TelegramBotWebHostBuilder.cs
+++ b/Telegrator.Hosting.Web/TelegramBotWebHostBuilder.cs
@@ -1,10 +1,73 @@
-using Telegrator.Hosting.Components;
-using Telegrator.Hosting.Web.Components;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+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.Hosting.Configuration;
+using Telegrator.Hosting.Providers;
+using Telegrator.MadiatorCore;
+#pragma warning disable IDE0001
namespace Telegrator.Hosting.Web
{
- public class TelegramBotWebHostBuilder //: ITelegramBotHostBuilder
+ ///
+ /// Represents a web hosted telegram bots and services builder that helps manage configuration, logging, lifetime, and more.
+ ///
+ public class TelegramBotWebHostBuilder : ITelegramBotHostBuilder
{
+ private readonly WebApplicationBuilder _innerBuilder;
+ private readonly TelegramBotWebOptions _settings;
+ private readonly HostHandlersCollection _handlers;
+ ///
+ public IHandlersCollection Handlers => _handlers;
+
+ ///
+ public IConfigurationManager Configuration => _innerBuilder.Configuration;
+
+ ///
+ public ILoggingBuilder Logging => _innerBuilder.Logging;
+
+ ///
+ public IServiceCollection Services => _innerBuilder.Services;
+
+ ///
+ public IHostEnvironment Environment => _innerBuilder.Environment;
+
+ internal TelegramBotWebHostBuilder(WebApplicationBuilder webApplicationBuilder, TelegramBotWebOptions settings)
+ {
+ _innerBuilder = webApplicationBuilder;
+ _settings = settings ?? throw new ArgumentNullException(nameof(settings));
+ _handlers = new HostHandlersCollection(Services, _settings);
+
+ Services.AddSingleton>(Options.Create(settings));
+ Services.Configure(Configuration.GetSection(nameof(TelegratorOptions)));
+ Services.Configure(Configuration.GetSection(nameof(TelegramBotClientOptions)), new TelegramBotClientOptionsProxy());
+ }
+
+ ///
+ /// Builds the host.
+ ///
+ ///
+ public TelegramBotWebHost Build()
+ {
+ foreach (PreBuildingRoutine preBuildRoutine in _handlers.PreBuilderRoutines)
+ {
+ try
+ {
+ preBuildRoutine.Invoke(this);
+ }
+ catch (NotImplementedException)
+ {
+ _ = 0xBAD + 0xC0DE;
+ }
+ }
+
+ return new TelegramBotWebHost(_innerBuilder, _handlers);
+ }
}
}
diff --git a/Telegrator.Hosting.Web/TelegramBotWebOptions.cs b/Telegrator.Hosting.Web/TelegramBotWebOptions.cs
index 6e2eceb..de18089 100644
--- a/Telegrator.Hosting.Web/TelegramBotWebOptions.cs
+++ b/Telegrator.Hosting.Web/TelegramBotWebOptions.cs
@@ -1,18 +1,58 @@
-using Telegrator.Configuration;
+using Microsoft.AspNetCore.Builder;
namespace Telegrator.Hosting.Web
{
- public class TelegramBotWebOptions : TelegramBotOptions
+ ///
+ /// Configuration options for Telegram bot behavior and execution settings.
+ /// Controls various aspects of bot operation including concurrency, routing, webhook receiving, and execution policies.
+ ///
+ public class TelegramBotWebOptions : TelegratorOptions
{
///
- /// Gets or sets uri for webhook update receiving
+ /// Gets or sets HTTPS URL to send updates to. Use an empty string to remove webhook integration
///
public required string WebhookUri { get; set; }
- public required string WebhookPattern { get; set; }
+ ///
+ /// A secret token to be sent in a header “X-Telegram-Bot-Api-Secret-Token” in every webhook request, 1-256 characters.
+ /// Only characters A-Z, a-z, 0-9, _ and - are allowed.
+ /// The header is useful to ensure that the request comes from a webhook set by you.
+ ///
+ public string? SecretToken { get; set; }
- public int MaxConnections { get; set; }
+ ///
+ /// The maximum allowed number of simultaneous HTTPS connections to the webhook for update delivery, 1-100. Defaults to 40.
+ /// Use lower values to limit the load on your bot's server, and higher values to increase your bot's throughput.
+ ///
+ public int MaxConnections { get; set; } = 40;
+ ///
+ /// Pass true to drop all pending updates
+ ///
public bool DropPendingUpdates { get; set; }
+
+ ///
+ public string[]? Args { get; init; }
+
+ ///
+ public string? EnvironmentName { get; init; }
+
+ ///
+ public string? ApplicationName { get; init; }
+
+ ///
+ public string? ContentRootPath { get; init; }
+
+ ///
+ public string? WebRootPath { get; init; }
+
+ internal WebApplicationOptions ToWebApplicationOptions() => new WebApplicationOptions()
+ {
+ ApplicationName = ApplicationName,
+ Args = Args,
+ ContentRootPath = ContentRootPath,
+ EnvironmentName = EnvironmentName,
+ WebRootPath = WebRootPath
+ };
}
}
diff --git a/Telegrator.Hosting.Web/Telegrator.Hosting.Web.csproj b/Telegrator.Hosting.Web/Telegrator.Hosting.Web.csproj
index a9bf70f..53790f9 100644
--- a/Telegrator.Hosting.Web/Telegrator.Hosting.Web.csproj
+++ b/Telegrator.Hosting.Web/Telegrator.Hosting.Web.csproj
@@ -4,6 +4,18 @@
net8.0
enable
enable
+ True
+ True
+
+ Telegrator : Telegram.Bot mediator framework
+ telegrator_nuget.png
+ https://github.com/Rikitav/Telegrator
+ telegram;bot;mediator;attributes;aspect;hosting;host;framework;easy;simple;handlers
+ True
+ True
+ LICENSE
+ README.md
+ 1.0.7
@@ -11,6 +23,25 @@
-
+
+ True
+ \
+
+
+ True
+ \
+
+
+ True
+ \
+
+
+
+
+
+
+
+
+
diff --git a/Telegrator.Hosting.Web/TypesExtensions.cs b/Telegrator.Hosting.Web/TypesExtensions.cs
index 7cb7f67..1482802 100644
--- a/Telegrator.Hosting.Web/TypesExtensions.cs
+++ b/Telegrator.Hosting.Web/TypesExtensions.cs
@@ -1,12 +1,22 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Telegram.Bot;
+using Telegrator.Hosting.Web.Components;
using Telegrator.Hosting.Web.Polling;
namespace Telegrator.Hosting.Web
{
+ ///
+ /// Contains extensions for
+ /// Provides method to configure
+ ///
public static class ServicesCollectionExtensions
{
+ ///
+ /// Registers service with to receive updates using webhook
+ ///
+ ///
+ ///
public static IServiceCollection AddTelegramWebhook(this IServiceCollection services)
{
services.AddHttpClient("tgwebhook").RemoveAllLoggers().AddTypedClient(TypedTelegramBotClientFactory);
diff --git a/Telegrator.Hosting/Components/IPreBuildingRoutine.cs b/Telegrator.Hosting/Components/IPreBuildingRoutine.cs
index 8e1fd14..c0c7f26 100644
--- a/Telegrator.Hosting/Components/IPreBuildingRoutine.cs
+++ b/Telegrator.Hosting/Components/IPreBuildingRoutine.cs
@@ -10,6 +10,6 @@
/// Executes the pre-building routine on the specified host builder.
///
/// The host builder to configure.
- public static abstract void PreBuildingRoutine(TelegramBotHostBuilder hostBuilder);
+ public static abstract void PreBuildingRoutine(ITelegramBotHostBuilder hostBuilder);
}
}
diff --git a/Telegrator.Hosting/Components/ITelegramBotHostBuilder.cs b/Telegrator.Hosting/Components/ITelegramBotHostBuilder.cs
index 69b40bd..59a1810 100644
--- a/Telegrator.Hosting/Components/ITelegramBotHostBuilder.cs
+++ b/Telegrator.Hosting/Components/ITelegramBotHostBuilder.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Telegrator.MadiatorCore;
diff --git a/Telegrator.Hosting/Configuration/TelegramBotClientOptionsProxy.cs b/Telegrator.Hosting/Configuration/TelegramBotClientOptionsProxy.cs
index 1f43344..e6786bc 100644
--- a/Telegrator.Hosting/Configuration/TelegramBotClientOptionsProxy.cs
+++ b/Telegrator.Hosting/Configuration/TelegramBotClientOptionsProxy.cs
@@ -6,7 +6,7 @@ namespace Telegrator.Hosting.Configuration
/// Internal proxy class for configuring Telegram bot client options from configuration.
/// Extends ConfigureOptionsProxy to provide specific configuration for Telegram bot client options.
///
- internal class TelegramBotClientOptionsProxy : ConfigureOptionsProxy
+ public class TelegramBotClientOptionsProxy : ConfigureOptionsProxy
{
///
/// Gets or sets the bot token.
diff --git a/Telegrator.Hosting/GlobalSuppressions.cs b/Telegrator.Hosting/GlobalSuppressions.cs
index cba9507..e8cd1b7 100644
--- a/Telegrator.Hosting/GlobalSuppressions.cs
+++ b/Telegrator.Hosting/GlobalSuppressions.cs
@@ -7,3 +7,4 @@ using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("Style", "IDE0290")]
[assembly: SuppressMessage("Style", "IDE0090")]
+[assembly: SuppressMessage("Usage", "CA2254")]
diff --git a/Telegrator.Hosting/Polling/HostUpdateHandlersPool.cs b/Telegrator.Hosting/Polling/HostUpdateHandlersPool.cs
index 35f3798..82bb1a2 100644
--- a/Telegrator.Hosting/Polling/HostUpdateHandlersPool.cs
+++ b/Telegrator.Hosting/Polling/HostUpdateHandlersPool.cs
@@ -1,13 +1,12 @@
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 options, ILogger logger) : UpdateHandlersPool(options.Value, options.Value.GlobalCancellationToken)
+ public class HostUpdateHandlersPool(IOptions options, ILogger logger) : UpdateHandlersPool(options.Value, options.Value.GlobalCancellationToken)
{
private readonly ILogger _logger = logger;
diff --git a/Telegrator.Hosting/Polling/HostUpdateRouter.cs b/Telegrator.Hosting/Polling/HostUpdateRouter.cs
index e949aef..be569d1 100644
--- a/Telegrator.Hosting/Polling/HostUpdateRouter.cs
+++ b/Telegrator.Hosting/Polling/HostUpdateRouter.cs
@@ -21,7 +21,7 @@ namespace Telegrator.Hosting.Polling
public HostUpdateRouter(
IHandlersProvider handlersProvider,
IAwaitingProvider awaitingProvider,
- IOptions options,
+ IOptions options,
IUpdateHandlersPool handlersPool,
ITelegramBotInfo botInfo,
ILogger logger) : base(handlersProvider, awaitingProvider, options.Value, handlersPool, botInfo)
@@ -33,7 +33,7 @@ namespace Telegrator.Hosting.Polling
///
public override Task HandleUpdateAsync(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken)
{
- //Logger.LogInformation("Received update of type \"{type}\"", update.Type);
+ Logger.LogInformation("Received update of type \"{type}\"", update.Type);
return base.HandleUpdateAsync(botClient, update, cancellationToken);
}
diff --git a/Telegrator.Hosting/Providers/HostAwaitingProvider.cs b/Telegrator.Hosting/Providers/HostAwaitingProvider.cs
index b7ec5e5..e5a9475 100644
--- a/Telegrator.Hosting/Providers/HostAwaitingProvider.cs
+++ b/Telegrator.Hosting/Providers/HostAwaitingProvider.cs
@@ -1,12 +1,11 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
-using Telegrator.Configuration;
using Telegrator.Providers;
namespace Telegrator.Hosting.Providers
{
///
- public class HostAwaitingProvider(IOptions options, ILogger logger) : AwaitingProvider(options.Value)
+ public class HostAwaitingProvider(IOptions options, ILogger logger) : AwaitingProvider(options.Value)
{
private readonly ILogger _logger = logger;
}
diff --git a/Telegrator.Hosting/Providers/HostHandlersCollection.cs b/Telegrator.Hosting/Providers/HostHandlersCollection.cs
index bef073c..39cd5ec 100644
--- a/Telegrator.Hosting/Providers/HostHandlersCollection.cs
+++ b/Telegrator.Hosting/Providers/HostHandlersCollection.cs
@@ -12,10 +12,10 @@ namespace Telegrator.Hosting.Providers
/// Pre host building task
///
///
- public delegate void PreBuildingRoutine(TelegramBotHostBuilder builder);
+ public delegate void PreBuildingRoutine(ITelegramBotHostBuilder builder);
///
- public class HostHandlersCollection(IServiceCollection hostServiceColletion, IHandlersCollectingOptions options) : HandlersCollection(options)
+ public class HostHandlersCollection(IServiceCollection hostServiceColletion, ITelegratorOptions options) : HandlersCollection(options)
{
private readonly IServiceCollection Services = hostServiceColletion;
diff --git a/Telegrator.Hosting/Providers/HostHandlersProvider.cs b/Telegrator.Hosting/Providers/HostHandlersProvider.cs
index a378b3a..75f7faa 100644
--- a/Telegrator.Hosting/Providers/HostHandlersProvider.cs
+++ b/Telegrator.Hosting/Providers/HostHandlersProvider.cs
@@ -1,7 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
-using Telegrator.Configuration;
using Telegrator.Handlers.Components;
using Telegrator.MadiatorCore;
using Telegrator.MadiatorCore.Descriptors;
@@ -18,7 +17,7 @@ namespace Telegrator.Hosting.Providers
///
public HostHandlersProvider(
IHandlersCollection handlers,
- IOptions options,
+ IOptions options,
IServiceProvider serviceProvider,
ILogger logger) : base(handlers, options.Value)
{
diff --git a/Telegrator.Hosting/README.md b/Telegrator.Hosting/README.md
new file mode 100644
index 0000000..41917e4
--- /dev/null
+++ b/Telegrator.Hosting/README.md
@@ -0,0 +1,93 @@
+# Telegrator.Hosting
+
+**Telegrator.Hosting** is an extension for the Telegrator framework that provides seamless integration with the .NET Generic Host, enabling production-ready, scalable, and maintainable Telegram bot applications.
+
+---
+
+## Features
+- Integration with `Microsoft.Extensions.Hosting` (background services, DI, configuration, logging)
+- Automatic handler discovery and registration
+- Strongly-typed configuration via `appsettings.json` and environment variables
+- Graceful startup/shutdown and lifecycle management
+- Advanced error handling and logging
+- Supports all Telegrator handler/filter/state features
+
+---
+
+## Requirements
+- .NET 8.0 or later
+- [Telegrator](https://github.com/Rikitav/Telegrator)
+
+---
+
+## Installation
+
+```shell
+dotnet add package Telegrator.Hosting
+```
+
+---
+
+## Quick Start Example
+
+**Program.cs:**
+```csharp
+using Telegrator.Hosting;
+
+// Creating builder
+TelegramBotHostBuilder builder = TelegramBotHost.CreateBuilder(new TelegramBotHostBuilderSettings()
+{
+ Args = args,
+ DescendDescriptorIndex = false,
+ ExceptIntersectingCommandAliases = true
+});
+
+// Registerring handlers
+builder.Handlers.CollectHandlersAssemblyWide();
+
+// Register your services
+builder.Services.AddSingleton();
+
+// Building and running application
+TelegramBotHost telegramBot = builder.Build();
+telegramBot.SetBotCommands();
+telegramBot.Run();
+```
+
+---
+
+## Configuration (appsettings.json)
+
+```json
+{
+ "TelegramBotClientOptions": {
+ "Token": "YOUR_BOT_TOKEN"
+ },
+
+ "HostOptions": {
+ "ShutdownTimeout": 10,
+ "BackgroundServiceExceptionBehavior": "StopHost"
+ },
+
+ "ReceiverOptions": {
+ "DropPendingUpdates": true,
+ "Limit": 10
+ }
+}
+```
+
+- `TelegramBotClientOptions`: Bot token and client settings
+- `HostOptions`: Host lifecycle and shutdown behavior
+- `ReceiverOptions`: Long-polling configuration
+
+---
+
+## Documentation
+- [Telegrator Main Docs](https://github.com/Rikitav/Telegrator)
+- [Getting Started Guide](https://github.com/Rikitav/Telegrator/wiki/Getting-started)
+- [Annotation Overview](https://github.com/Rikitav/Telegrator/wiki/Annotation-overview)
+
+---
+
+## License
+GPLv3
\ No newline at end of file
diff --git a/Telegrator.Hosting/TelegramBotHost.cs b/Telegrator.Hosting/TelegramBotHost.cs
index cb5fca1..878db88 100644
--- a/Telegrator.Hosting/TelegramBotHost.cs
+++ b/Telegrator.Hosting/TelegramBotHost.cs
@@ -114,6 +114,8 @@ namespace Telegrator.Hosting
if (_disposed)
return;
+ _innerHost.Dispose();
+
GC.SuppressFinalize(this);
_disposed = true;
}
diff --git a/Telegrator.Hosting/TelegramBotHostBuilder.cs b/Telegrator.Hosting/TelegramBotHostBuilder.cs
index 80cc490..fc1ef65 100644
--- a/Telegrator.Hosting/TelegramBotHostBuilder.cs
+++ b/Telegrator.Hosting/TelegramBotHostBuilder.cs
@@ -4,10 +4,9 @@ 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.Configuration;
using Telegrator.Hosting.Providers;
using Telegrator.MadiatorCore;
@@ -51,7 +50,7 @@ namespace Telegrator.Hosting
_innerBuilder.Logging.ClearProviders();
- Services.Configure(Configuration.GetSection(nameof(TelegramBotOptions)));
+ Services.Configure(Configuration.GetSection(nameof(TelegratorOptions)));
Services.Configure(Configuration.GetSection(nameof(ReceiverOptions)));
Services.Configure(Configuration.GetSection(nameof(TelegramBotClientOptions)), new TelegramBotClientOptionsProxy());
}
diff --git a/Telegrator.Hosting/TelegramBotHostBuilderSettings.cs b/Telegrator.Hosting/TelegramBotHostBuilderSettings.cs
index 3e7d1bf..6f3b891 100644
--- a/Telegrator.Hosting/TelegramBotHostBuilderSettings.cs
+++ b/Telegrator.Hosting/TelegramBotHostBuilderSettings.cs
@@ -1,13 +1,12 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
-using Telegrator.Configuration;
namespace Telegrator.Hosting
{
///
/// Settings os hosted Telegram bot
///
- public class TelegramBotHostBuilderSettings() : IHandlersCollectingOptions
+ public class TelegramBotHostBuilderSettings() : TelegratorOptions
{
///
public bool DisableDefaults { get; set; }
@@ -27,12 +26,6 @@ namespace Telegrator.Hosting
///
public string? ContentRootPath { get; set; }
- ///
- public bool DescendDescriptorIndex { get; set; } = true;
-
- ///
- public bool ExceptIntersectingCommandAliases { get; set; } = true;
-
internal HostApplicationBuilderSettings ToApplicationBuilderSettings() => new HostApplicationBuilderSettings()
{
DisableDefaults = DisableDefaults,
diff --git a/Telegrator.Hosting/Telegrator.Hosting.csproj b/Telegrator.Hosting/Telegrator.Hosting.csproj
index dc65e1d..19ace06 100644
--- a/Telegrator.Hosting/Telegrator.Hosting.csproj
+++ b/Telegrator.Hosting/Telegrator.Hosting.csproj
@@ -15,7 +15,8 @@
True
True
LICENSE
- 1.0.6
+ README.md
+ 1.0.7
@@ -38,4 +39,11 @@
+
+
+ True
+ \
+
+
+
diff --git a/Telegrator.Hosting/TypesExtensions.cs b/Telegrator.Hosting/TypesExtensions.cs
index de8f8ce..3ea32be 100644
--- a/Telegrator.Hosting/TypesExtensions.cs
+++ b/Telegrator.Hosting/TypesExtensions.cs
@@ -4,7 +4,6 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
-using System.Runtime.CompilerServices;
using Telegram.Bot;
using Telegram.Bot.Types;
using Telegrator.Configuration;
diff --git a/Telegrator.sln b/Telegrator.sln
index 84f7362..60116a7 100644
--- a/Telegrator.sln
+++ b/Telegrator.sln
@@ -20,6 +20,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Telegrator.Analyzers", "Tel
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Telegrator.ConsoleHost", "..\Telegram.Reactive.TestApps\Telegrator.ConsoleHost\Telegrator.ConsoleHost.csproj", "{78691EF7-6009-3BB1-C90D-1D1D95442041}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Telegrator.Hosting.Web", "Telegrator.Hosting.Web\Telegrator.Hosting.Web.csproj", "{98AB490F-6A36-CCFF-F6E6-B029D1665965}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Telegrator.ConsoleHost.Web", "Telegrator.ConsoleHost.Web\Telegrator.ConsoleHost.Web.csproj", "{C18E1844-64A7-4FF8-BDB9-24F8FBFC5CF6}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
AnalyzersDebug|Any CPU = AnalyzersDebug|Any CPU
@@ -63,6 +67,18 @@ Global
{78691EF7-6009-3BB1-C90D-1D1D95442041}.Debug|Any CPU.Build.0 = Debug|Any CPU
{78691EF7-6009-3BB1-C90D-1D1D95442041}.Release|Any CPU.ActiveCfg = Release|Any CPU
{78691EF7-6009-3BB1-C90D-1D1D95442041}.Release|Any CPU.Build.0 = Release|Any CPU
+ {98AB490F-6A36-CCFF-F6E6-B029D1665965}.AnalyzersDebug|Any CPU.ActiveCfg = Release|Any CPU
+ {98AB490F-6A36-CCFF-F6E6-B029D1665965}.AnalyzersDebug|Any CPU.Build.0 = Release|Any CPU
+ {98AB490F-6A36-CCFF-F6E6-B029D1665965}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {98AB490F-6A36-CCFF-F6E6-B029D1665965}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {98AB490F-6A36-CCFF-F6E6-B029D1665965}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {98AB490F-6A36-CCFF-F6E6-B029D1665965}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C18E1844-64A7-4FF8-BDB9-24F8FBFC5CF6}.AnalyzersDebug|Any CPU.ActiveCfg = Release|Any CPU
+ {C18E1844-64A7-4FF8-BDB9-24F8FBFC5CF6}.AnalyzersDebug|Any CPU.Build.0 = Release|Any CPU
+ {C18E1844-64A7-4FF8-BDB9-24F8FBFC5CF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C18E1844-64A7-4FF8-BDB9-24F8FBFC5CF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C18E1844-64A7-4FF8-BDB9-24F8FBFC5CF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C18E1844-64A7-4FF8-BDB9-24F8FBFC5CF6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Telegrator/Attributes/StateKeeperAttribute.cs b/Telegrator/Attributes/StateKeeperAttribute.cs
index 85ac133..dcf0e02 100644
--- a/Telegrator/Attributes/StateKeeperAttribute.cs
+++ b/Telegrator/Attributes/StateKeeperAttribute.cs
@@ -64,36 +64,6 @@ namespace Telegrator.Attributes
SpecialState = specialState;
}
- /*
- ///
- /// Initializes the attribute with a custom state keeper, a specific state, and a custom key resolver.
- ///
- /// The state keeper instance
- /// The state value to associate
- /// The key resolver for state keeping
- protected StateKeeperAttribute(TKeeper keeper, TState myState, IStateKeyResolver keyResolver) : base(typeof(TKeeper))
- {
- StateKeeper ??= keeper;
- StateKeeper.KeyResolver = keyResolver;
- MyState = myState;
- SpecialState = SpecialState.None;
- }
-
- ///
- /// Initializes the attribute with a custom state keeper, a special state, and a custom key resolver.
- ///
- /// The state keeper instance
- /// The special state mode
- /// The key resolver for state keeping
- protected StateKeeperAttribute(TKeeper keeper, SpecialState specialState, IStateKeyResolver keyResolver) : base(typeof(TKeeper))
- {
- StateKeeper ??= keeper;
- StateKeeper.KeyResolver = keyResolver;
- MyState = StateKeeper.DefaultState;
- SpecialState = specialState;
- }
- */
-
///
/// Determines whether the current update context passes the state filter.
///
diff --git a/Telegrator/Configuration/IHandlersCollectingOptions.cs b/Telegrator/Configuration/IHandlersCollectingOptions.cs
deleted file mode 100644
index 912aba5..0000000
--- a/Telegrator/Configuration/IHandlersCollectingOptions.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-namespace Telegrator.Configuration
-{
- ///
- /// Interface for configuring handler collection behavior.
- /// Defines options that control how handlers are collected and processed during initialization.
- ///
- public interface IHandlersCollectingOptions
- {
- ///
- /// Gets or sets a value indicating whether to descend the indexr of handler's index on register. ('false' by default)
- ///
- public bool DescendDescriptorIndex { get; set; }
-
- ///
- /// Gets or sets a value indicating whether to exclude intersecting command aliases.
- ///
- public bool ExceptIntersectingCommandAliases { get; set; }
- }
-}
diff --git a/Telegrator/Configuration/TelegramBotOptions.cs b/Telegrator/Configuration/ITelegratorOptions.cs
similarity index 63%
rename from Telegrator/Configuration/TelegramBotOptions.cs
rename to Telegrator/Configuration/ITelegratorOptions.cs
index 57f90ef..82b61b9 100644
--- a/Telegrator/Configuration/TelegramBotOptions.cs
+++ b/Telegrator/Configuration/ITelegratorOptions.cs
@@ -1,10 +1,10 @@
namespace Telegrator.Configuration
{
///
- /// Configuration options for Telegram bot behavior and execution settings.
- /// Controls various aspects of bot operation including concurrency, routing, and execution policies.
+ /// Interface for configuring Telegram bot behavior and execution settings.
+ /// Controls various aspects of bot operation including concurrency, routing, collecting, and execution policies.
///
- public class TelegramBotOptions
+ public interface ITelegratorOptions
{
///
/// Gets or sets a value indicating whether only the first found handler should be executed for each update.
@@ -25,5 +25,15 @@
/// Gets or sets the global cancellation token for all bot operations.
///
public CancellationToken GlobalCancellationToken { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether to descend the indexr of handler's index on register. ('false' by default)
+ ///
+ public bool DescendDescriptorIndex { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether to exclude intersecting command aliases.
+ ///
+ public bool ExceptIntersectingCommandAliases { get; set; }
}
}
diff --git a/Telegrator/Enums.cs b/Telegrator/Enums.cs
index 6326246..aa0c4a0 100644
--- a/Telegrator/Enums.cs
+++ b/Telegrator/Enums.cs
@@ -76,6 +76,11 @@
[Flags]
public enum DebugLevel
{
+ ///
+ /// None to write
+ ///
+ None = 0x0,
+
///
/// Write debug messages from filters execution
///
diff --git a/Telegrator/LeveledDebug.cs b/Telegrator/LeveledDebug.cs
index 2a02515..6f810d9 100644
--- a/Telegrator/LeveledDebug.cs
+++ b/Telegrator/LeveledDebug.cs
@@ -1,5 +1,4 @@
using System.Diagnostics;
-using Telegram.Bot.Types.Enums;
namespace Telegrator
{
@@ -8,13 +7,18 @@ namespace Telegrator
///
public static class LeveledDebug
{
+ ///
+ /// Gets or sets flags of what debug messages to write
+ ///
+ public static DebugLevel IndentFlags { get; set; } = DebugLevel.None;
+
///
/// Writes debug message if Indent level has Router flag
///
///
public static void RouterWriteLine(string message)
{
- if (Debug.IndentLevel.HasFlag(DebugLevel.Router))
+ if (IndentFlags.HasFlag(DebugLevel.Router))
Debug.WriteLine(message);
}
@@ -25,7 +29,7 @@ namespace Telegrator
///
public static void RouterWriteLine(string message, params object[] args)
{
- if (Debug.IndentLevel.HasFlag(DebugLevel.Router))
+ if (IndentFlags.HasFlag(DebugLevel.Router))
Debug.WriteLine(message, args);
}
@@ -35,7 +39,7 @@ namespace Telegrator
///
public static void ProviderWriteLine(string message)
{
- if (Debug.IndentLevel.HasFlag(DebugLevel.Providers))
+ if (IndentFlags.HasFlag(DebugLevel.Providers))
Debug.WriteLine(message);
}
@@ -46,7 +50,7 @@ namespace Telegrator
///
public static void ProviderWriteLine(string message, params object[] args)
{
- if (Debug.IndentLevel.HasFlag(DebugLevel.Providers))
+ if (IndentFlags.HasFlag(DebugLevel.Providers))
Debug.WriteLine(message, args);
}
@@ -56,7 +60,7 @@ namespace Telegrator
///
public static void FilterWriteLine(string message)
{
- if (Debug.IndentLevel.HasFlag(DebugLevel.Filters))
+ if (IndentFlags.HasFlag(DebugLevel.Filters))
Debug.WriteLine(message);
}
@@ -67,7 +71,7 @@ namespace Telegrator
///
public static void FilterWriteLine(string message, params object[] args)
{
- if (Debug.IndentLevel.HasFlag(DebugLevel.Filters))
+ if (IndentFlags.HasFlag(DebugLevel.Filters))
Debug.WriteLine(message, args);
}
@@ -77,7 +81,7 @@ namespace Telegrator
///
public static void PoolWriteLine(string message)
{
- if (Debug.IndentLevel.HasFlag(DebugLevel.HandlersPool))
+ if (IndentFlags.HasFlag(DebugLevel.HandlersPool))
Debug.WriteLine(message);
}
@@ -88,7 +92,7 @@ namespace Telegrator
///
public static void PoolWriteLine(string message, params object[] args)
{
- if (Debug.IndentLevel.HasFlag(DebugLevel.HandlersPool))
+ if (IndentFlags.HasFlag(DebugLevel.HandlersPool))
Debug.WriteLine(message, args);
}
}
diff --git a/Telegrator/MadiatorCore/Descriptors/DescriptorFiltersSet.cs b/Telegrator/MadiatorCore/Descriptors/DescriptorFiltersSet.cs
index 2d58018..fc73f62 100644
--- a/Telegrator/MadiatorCore/Descriptors/DescriptorFiltersSet.cs
+++ b/Telegrator/MadiatorCore/Descriptors/DescriptorFiltersSet.cs
@@ -47,7 +47,7 @@ namespace Telegrator.MadiatorCore.Descriptors
{
if (!UpdateValidator.CanPass(filterContext))
{
- LeveledDebug.FilterWriteLine("(E) UpdateValidator filter of {0} for Update ({2}) didnt pass!", filterContext.Data["handler_name"]);
+ LeveledDebug.FilterWriteLine("(E) UpdateValidator filter of {0} for Update ({1}) didnt pass!", filterContext.Data["handler_name"], filterContext.Update.Id);
return false;
}
@@ -59,7 +59,7 @@ namespace Telegrator.MadiatorCore.Descriptors
{
if (!StateKeeperValidator.CanPass(filterContext))
{
- LeveledDebug.FilterWriteLine("(E) StateKeeperValidator filter of {0} for Update ({2}) didnt pass!", filterContext.Data["handler_name"]);
+ LeveledDebug.FilterWriteLine("(E) StateKeeperValidator filter of {0} for Update ({1}) didnt pass!", filterContext.Data["handler_name"], filterContext.Update.Id);
return false;
}
@@ -74,7 +74,7 @@ namespace Telegrator.MadiatorCore.Descriptors
if (!filter.CanPass(filterContext))
{
if (filter is not AnonymousCompiledFilter && filter is not AnonymousTypeFilter)
- LeveledDebug.FilterWriteLine("(E) {0} filter of {1} didnt pass!", filter.GetType().Name, filterContext.Data["handler_name"]);
+ LeveledDebug.FilterWriteLine("(E) {0} filter of {1} for Update ({2}) didnt pass!", filter.GetType().Name, filterContext.Data["handler_name"], filterContext.Update.Id);
return false;
}
diff --git a/Telegrator/MadiatorCore/Descriptors/HandlerDescriptorList.cs b/Telegrator/MadiatorCore/Descriptors/HandlerDescriptorList.cs
index 660deae..4430864 100644
--- a/Telegrator/MadiatorCore/Descriptors/HandlerDescriptorList.cs
+++ b/Telegrator/MadiatorCore/Descriptors/HandlerDescriptorList.cs
@@ -12,7 +12,7 @@ namespace Telegrator.MadiatorCore.Descriptors
{
private readonly object _lock = new object();
private readonly SortedList _innerCollection;
- private readonly IHandlersCollectingOptions? _options;
+ private readonly ITelegratorOptions? _options;
private readonly UpdateType _handlingType;
private int count;
@@ -54,7 +54,7 @@ namespace Telegrator.MadiatorCore.Descriptors
///
/// The update type for the handlers.
/// The collecting options.
- public HandlerDescriptorList(UpdateType updateType, IHandlersCollectingOptions? options)
+ public HandlerDescriptorList(UpdateType updateType, ITelegratorOptions? options)
{
_innerCollection = [];
_handlingType = updateType;
diff --git a/Telegrator/MadiatorCore/IUpdateRouter.cs b/Telegrator/MadiatorCore/IUpdateRouter.cs
index 6992231..53fbe87 100644
--- a/Telegrator/MadiatorCore/IUpdateRouter.cs
+++ b/Telegrator/MadiatorCore/IUpdateRouter.cs
@@ -1,5 +1,4 @@
using Telegram.Bot.Polling;
-using Telegrator.Configuration;
using Telegrator.Handlers.Components;
namespace Telegrator.MadiatorCore
@@ -11,9 +10,9 @@ namespace Telegrator.MadiatorCore
public interface IUpdateRouter : IUpdateHandler, IPollingProvider
{
///
- /// Gets the for the router.
+ /// Gets the for the router.
///
- public TelegramBotOptions Options { get; }
+ public TelegratorOptions Options { get; }
///
/// Gets the that manages handler execution.
diff --git a/Telegrator/Polling/UpdateHandlersPool.cs b/Telegrator/Polling/UpdateHandlersPool.cs
index c4a029d..b1a3ee9 100644
--- a/Telegrator/Polling/UpdateHandlersPool.cs
+++ b/Telegrator/Polling/UpdateHandlersPool.cs
@@ -1,5 +1,4 @@
using System.Collections.Concurrent;
-using Telegrator.Configuration;
using Telegrator.MadiatorCore;
using Telegrator.MadiatorCore.Descriptors;
@@ -39,7 +38,7 @@ namespace Telegrator.Polling
///
/// The bot configuration options.
///
- protected readonly TelegramBotOptions Options;
+ protected readonly TelegratorOptions Options;
///
/// The global cancellation token for stopping all operations.
@@ -62,7 +61,7 @@ namespace Telegrator.Polling
///
/// The bot configuration options.
/// The global cancellation token.
- public UpdateHandlersPool(TelegramBotOptions options, CancellationToken globalCancellationToken)
+ public UpdateHandlersPool(TelegratorOptions options, CancellationToken globalCancellationToken)
{
Options = options;
GlobalCancellationToken = globalCancellationToken;
diff --git a/Telegrator/Polling/UpdateRouter.cs b/Telegrator/Polling/UpdateRouter.cs
index bd8e9ce..fb6811c 100644
--- a/Telegrator/Polling/UpdateRouter.cs
+++ b/Telegrator/Polling/UpdateRouter.cs
@@ -17,7 +17,7 @@ namespace Telegrator.Polling
///
public class UpdateRouter : IUpdateRouter
{
- private readonly TelegramBotOptions _options;
+ private readonly TelegratorOptions _options;
private readonly IHandlersProvider _handlersProvider;
private readonly IAwaitingProvider _awaitingProvider;
private readonly IUpdateHandlersPool _HandlersPool;
@@ -30,7 +30,7 @@ namespace Telegrator.Polling
public IAwaitingProvider AwaitingProvider => _awaitingProvider;
///
- public TelegramBotOptions Options => _options;
+ public TelegratorOptions Options => _options;
///
public IUpdateHandlersPool HandlersPool => _HandlersPool;
@@ -48,7 +48,7 @@ namespace Telegrator.Polling
/// The provider for awaiting handlers.
/// The bot configuration options.
///
- public UpdateRouter(IHandlersProvider handlersProvider, IAwaitingProvider awaitingProvider, TelegramBotOptions options, ITelegramBotInfo botInfo)
+ public UpdateRouter(IHandlersProvider handlersProvider, IAwaitingProvider awaitingProvider, TelegratorOptions options, ITelegramBotInfo botInfo)
{
_options = options;
_handlersProvider = handlersProvider;
@@ -65,7 +65,7 @@ namespace Telegrator.Polling
/// The bot configuration options.
/// The custom handlers pool to use.
///
- public UpdateRouter(IHandlersProvider handlersProvider, IAwaitingProvider awaitingProvider, TelegramBotOptions options, IUpdateHandlersPool handlersPool, ITelegramBotInfo botInfo)
+ public UpdateRouter(IHandlersProvider handlersProvider, IAwaitingProvider awaitingProvider, TelegratorOptions options, IUpdateHandlersPool handlersPool, ITelegramBotInfo botInfo)
{
_options = options;
_handlersProvider = handlersProvider;
@@ -149,22 +149,22 @@ namespace Telegrator.Polling
/// A collection of described handler information for the update
protected virtual IEnumerable GetHandlers(IHandlersProvider provider, IUpdateRouter updateRouter, ITelegramBotClient client, Update update, CancellationToken cancellationToken = default)
{
- LeveledDebug.ProviderWriteLine("Requested handlers for UpdateType.{0}", update.Type);
+ LeveledDebug.RouterWriteLine("Requested handlers for UpdateType.{0}", update.Type);
if (!provider.TryGetDescriptorList(update.Type, out HandlerDescriptorList? descriptors))
{
- LeveledDebug.ProviderWriteLine("No registered, providing Any");
+ LeveledDebug.RouterWriteLine("No registered, providing Any");
provider.TryGetDescriptorList(UpdateType.Unknown, out descriptors);
}
if (descriptors == null || descriptors.Count == 0)
{
- LeveledDebug.ProviderWriteLine("No handlers provided");
+ LeveledDebug.RouterWriteLine("No handlers provided");
return [];
}
IEnumerable described = DescribeDescriptors(provider, descriptors, updateRouter, client, update, cancellationToken);
- LeveledDebug.ProviderWriteLine("Described total of {0} handlers for Update ({1}) from {2} provider", described.Count(), update.Id, provider.GetType().Name);
- LeveledDebug.ProviderWriteLine("Described handlers : {0}", string.Join(", ", described));
+ LeveledDebug.RouterWriteLine("Described total of {0} handlers for Update ({1}) from {2} provider", described.Count(), update.Id, provider.GetType().Name);
+ LeveledDebug.RouterWriteLine("Described handlers : {0}", string.Join(", ", described));
return described;
}
@@ -183,7 +183,7 @@ namespace Telegrator.Polling
{
try
{
- LeveledDebug.ProviderWriteLine("Describing descriptors of descriptorsList.HandlingType.{0} for Update ({1})", descriptors.HandlingType, update.Id);
+ LeveledDebug.RouterWriteLine("Describing descriptors of descriptorsList.HandlingType.{0} for Update ({1})", descriptors.HandlingType, update.Id);
foreach (HandlerDescriptor descriptor in descriptors.Reverse())
{
cancellationToken.ThrowIfCancellationRequested();
@@ -198,7 +198,7 @@ namespace Telegrator.Polling
}
finally
{
- LeveledDebug.ProviderWriteLine("Describing for Update ({0}) finished", update.Id);
+ LeveledDebug.RouterWriteLine("Describing for Update ({0}) finished", update.Id);
}
}
@@ -247,7 +247,25 @@ namespace Telegrator.Polling
sb.AppendFormat(" from {0} ({1})", msg.From.Username, msg.From.Id);
if (msg.Text != null)
- sb.AppendFormat("'{0}'", msg.Text);
+ sb.AppendFormat(" with text '{0}'", msg.Text);
+
+ if (msg.Sticker != null)
+ sb.AppendFormat(" with sticker '{0}'", msg.Sticker.Emoji);
+
+ LeveledDebug.RouterWriteLine(sb.ToString());
+ break;
+ }
+
+ case UpdateType.CallbackQuery:
+ {
+ CallbackQuery cq = update.CallbackQuery ?? throw new NullReferenceException();
+ StringBuilder sb = new StringBuilder("Update.CallbackQuery");
+
+ if (cq.From != null)
+ sb.AppendFormat(" from {0} ({1})", cq.From.Username, cq.From.Id);
+
+ if (cq.From != null)
+ sb.AppendFormat(" with data '{0}'", cq.Data);
LeveledDebug.RouterWriteLine(sb.ToString());
break;
diff --git a/Telegrator/Providers/AwaitingProvider.cs b/Telegrator/Providers/AwaitingProvider.cs
index 49ad817..356e35e 100644
--- a/Telegrator/Providers/AwaitingProvider.cs
+++ b/Telegrator/Providers/AwaitingProvider.cs
@@ -1,5 +1,4 @@
using Telegram.Bot.Types.Enums;
-using Telegrator.Configuration;
using Telegrator.MadiatorCore;
using Telegrator.MadiatorCore.Descriptors;
@@ -10,7 +9,7 @@ namespace Telegrator.Providers
/// Extends HandlersProvider to provide functionality for creating and managing awaiter handlers.
///
/// The bot configuration options.
- public class AwaitingProvider(TelegramBotOptions options) : HandlersProvider([], options), IAwaitingProvider
+ public class AwaitingProvider(TelegratorOptions options) : HandlersProvider([], options), IAwaitingProvider
{
///
/// List of handler descriptors for awaiting handlers.
diff --git a/Telegrator/Providers/HandlersCollection.cs b/Telegrator/Providers/HandlersCollection.cs
index ecb0f4b..0ecb87d 100644
--- a/Telegrator/Providers/HandlersCollection.cs
+++ b/Telegrator/Providers/HandlersCollection.cs
@@ -14,7 +14,7 @@ namespace Telegrator.Providers
/// Provides functionality for collecting, adding, and organizing handlers.
///
/// Optional configuration options for handler collecting.
- public class HandlersCollection(IHandlersCollectingOptions? options) : IHandlersCollection
+ public class HandlersCollection(ITelegratorOptions? options) : IHandlersCollection
{
private readonly List _allowedTypes = [];
@@ -26,7 +26,7 @@ namespace Telegrator.Providers
///
/// Configuration options for handler collecting.
///
- protected readonly IHandlersCollectingOptions? Options = options;
+ protected readonly ITelegratorOptions? Options = options;
///
/// Gets whether handlers must have a parameterless constructor.
diff --git a/Telegrator/Providers/HandlersProvider.cs b/Telegrator/Providers/HandlersProvider.cs
index fed5f5f..fb8a7f9 100644
--- a/Telegrator/Providers/HandlersProvider.cs
+++ b/Telegrator/Providers/HandlersProvider.cs
@@ -2,7 +2,6 @@
using System.Runtime.CompilerServices;
using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
-using Telegrator.Configuration;
using Telegrator.Handlers.Components;
using Telegrator.MadiatorCore;
using Telegrator.MadiatorCore.Descriptors;
@@ -28,7 +27,7 @@ namespace Telegrator.Providers
///
/// Configuration options for the bot and handler execution behavior.
///
- protected readonly TelegramBotOptions Options;
+ protected readonly TelegratorOptions Options;
///
/// Initializes a new instance of with the specified handler collections and configuration.
@@ -36,11 +35,12 @@ namespace Telegrator.Providers
/// Collection of handler descriptor lists organized by update type
/// Configuration options for the bot and handler execution
/// Thrown when options or botInfo is null
- public HandlersProvider(IHandlersCollection handlers, TelegramBotOptions options)
+ public HandlersProvider(IHandlersCollection handlers, TelegratorOptions options)
{
AllowedTypes = handlers.AllowedTypes;
HandlersDictionary = handlers.Values.ForEach(list => list.Freeze()).ToReadOnlyDictionary(list => list.HandlingType);
Options = options ?? throw new ArgumentNullException(nameof(options));
+ LeveledDebug.ProviderWriteLine("{0} created!", GetType().Name);
}
///
@@ -49,27 +49,36 @@ namespace Telegrator.Providers
/// Collection of handler descriptor lists organized by update type
/// Configuration options for the bot and handler execution
/// Thrown when options or botInfo is null
- public HandlersProvider(IEnumerable handlers, TelegramBotOptions options)
+ public HandlersProvider(IEnumerable handlers, TelegratorOptions options)
{
AllowedTypes = Update.AllTypes;
HandlersDictionary = handlers.ForEach(list => list.Freeze()).ToReadOnlyDictionary(list => list.HandlingType);
Options = options ?? throw new ArgumentNullException(nameof(options));
+ LeveledDebug.ProviderWriteLine("{0} created!", GetType().Name);
}
///
/// Thrown when the descriptor type is not recognized
public virtual UpdateHandlerBase GetHandlerInstance(HandlerDescriptor descriptor, CancellationToken cancellationToken = default)
{
- cancellationToken.ThrowIfCancellationRequested();
- bool useSingleton = UseSingleton(descriptor);
+ try
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ bool useSingleton = UseSingleton(descriptor);
- if (useSingleton && descriptor.SingletonInstance != null)
- return descriptor.SingletonInstance;
+ if (useSingleton && descriptor.SingletonInstance != null)
+ return descriptor.SingletonInstance;
- UpdateHandlerBase instance = GetHandlerInstanceInternal(descriptor);
- descriptor.SingletonInstance = useSingleton ? instance : null;
- descriptor.LazyInitialization?.Invoke(instance);
- return instance;
+ UpdateHandlerBase instance = GetHandlerInstanceInternal(descriptor);
+ descriptor.SingletonInstance = useSingleton ? instance : null;
+ descriptor.LazyInitialization?.Invoke(instance);
+ return instance;
+ }
+ catch
+ {
+ LeveledDebug.ProviderWriteLine("Failed to create instance of {0}", descriptor.ToString());
+ throw;
+ }
}
private static UpdateHandlerBase GetHandlerInstanceInternal(HandlerDescriptor descriptor)
@@ -84,7 +93,7 @@ namespace Telegrator.Providers
{
DescriptorType.General or DescriptorType.Keyed => false,
DescriptorType.Implicit or DescriptorType.Singleton => true,
- _ => throw new Exception()
+ _ => throw new Exception("Unknown decriptor type")
};
///
diff --git a/Telegrator/Telegrator.csproj b/Telegrator/Telegrator.csproj
index 952510e..cd0d8fa 100644
--- a/Telegrator/Telegrator.csproj
+++ b/Telegrator/Telegrator.csproj
@@ -17,7 +17,7 @@
True
True
LICENSE
- 1.0.6
+ 1.0.7
diff --git a/Telegrator/TelegratorClient.cs b/Telegrator/TelegratorClient.cs
index 73e760e..499d1b3 100644
--- a/Telegrator/TelegratorClient.cs
+++ b/Telegrator/TelegratorClient.cs
@@ -19,7 +19,7 @@ namespace Telegrator
private IUpdateRouter? updateRouter = null;
///
- public TelegramBotOptions Options { get; private set; }
+ public TelegratorOptions Options { get; private set; }
///
public IHandlersCollection Handlers { get; private set; }
@@ -47,7 +47,7 @@ namespace Telegrator
/// The cancellation token.
public TelegratorClient(TelegramBotClientOptions options, HttpClient? httpClient = null, CancellationToken cancellationToken = default) : base(options, httpClient, cancellationToken)
{
- Options = new TelegramBotOptions();
+ Options = new TelegratorOptions();
Handlers = new HandlersCollection(default);
BotInfo = new TelegramBotInfo(this.GetMe(cancellationToken).Result);
}
diff --git a/Telegrator/TelegratorOptions.cs b/Telegrator/TelegratorOptions.cs
new file mode 100644
index 0000000..6343b2d
--- /dev/null
+++ b/Telegrator/TelegratorOptions.cs
@@ -0,0 +1,30 @@
+using Telegrator.Configuration;
+
+namespace Telegrator
+{
+ ///
+ /// Configuration options for Telegram bot behavior and execution settings.
+ /// Controls various aspects of bot operation including concurrency, routing, and execution policies.
+ ///
+ public class TelegratorOptions : ITelegratorOptions
+ {
+ ///
+ public bool ExecuteOnlyFirstFoundHanlder { get; set; }
+
+ ///
+ public int? MaximumParallelWorkingHandlers { get; set; }
+
+ ///
+ public bool ExclusiveAwaitingHandlerRouting { get; set; }
+
+ ///
+ public CancellationToken GlobalCancellationToken { get; set; }
+
+ ///
+ public bool DescendDescriptorIndex { get; set; } = true;
+
+ ///
+ public bool ExceptIntersectingCommandAliases { get; set; } = true;
+
+ }
+}