8 Commits

Author SHA1 Message Date
gutii e9569545d8 * Added missing summaries 2026-05-01 20:50:56 +04:00
gutii 39f9abd9de * Added WideBotOptions
* Added ConfigureWideBot method
* Refactored `AddWideTelegrator` method
* Added `dbConnectionFactory`
2026-05-01 20:48:32 +04:00
gutii 6453e42d06 * Added link to new documenation site to README 2026-04-29 23:38:38 +04:00
gutii 9901077213 * Added webhooking detection 2026-04-27 22:15:39 +04:00
gutii 96b3241716 * Added StartReceiving method as ITelegratoBot interface member
* Added missing summaries
* Fixed compiler warning and infos
* Code cleanup and bugfixes
2026-04-27 22:13:47 +04:00
gutii 5433a2de0d * Fixed Result behaviour
* Added AsWClient
* Updated examples
2026-04-27 21:07:02 +04:00
gutii 0e0a280308 * Added WideBot csproj data
* Added TelegratorWideClient
* Added WClient extension property for handlers
* Code cleanup
2026-04-27 16:28:20 +04:00
gutii aba9cf4037 * Added integration addon wit WTelegramBot (WIP)
* Added some extensions methods
* Refactored Result behaviour
* Added missing exception messages
* Removed telegrator-specific host builder (obsolete)
* Code cleanup and bug fixes
2026-04-27 09:56:44 +04:00
57 changed files with 1633 additions and 1136 deletions
+4
View File
@@ -8,6 +8,10 @@ Telegrator is a modern C# framework for building Telegram bots, inspired by AOP
--- ---
## Learn and Docs
Learn Telegrator on [Official documentation site](https://rikitav.github.io/telegrator.docs).
The documentation may not be completely transparent, informative or even actual to latest version, so if you have any questions or problems, please write them in the [Telegram.Bot](https://t.me/joinchat/B35YY0QbLfd034CFnvCtCA) group. I am a member of this group and will notice you! If you have any suggestions or want to participate in building documentation, make push requests and open issues on this repository! The documentation may not be completely transparent, informative or even actual to latest version, so if you have any questions or problems, please write them in the [Telegram.Bot](https://t.me/joinchat/B35YY0QbLfd034CFnvCtCA) group. I am a member of this group and will notice you! If you have any suggestions or want to participate in building documentation, make push requests and open issues on this repository!
--- ---
+1
View File
@@ -4,6 +4,7 @@
<Project Path="src/Telegrator.Analyzers/Telegrator.Analyzers.csproj" /> <Project Path="src/Telegrator.Analyzers/Telegrator.Analyzers.csproj" />
<Project Path="src/Telegrator.Hosting.Web/Telegrator.Hosting.Web.csproj" /> <Project Path="src/Telegrator.Hosting.Web/Telegrator.Hosting.Web.csproj" />
<Project Path="src/Telegrator.Hosting/Telegrator.Hosting.csproj" /> <Project Path="src/Telegrator.Hosting/Telegrator.Hosting.csproj" />
<Project Path="src/Telegrator.Hosting.WideBot/Telegrator.Hosting.WideBot.csproj" />
<Project Path="src/Telegrator.Localized/Telegrator.Localized.csproj" /> <Project Path="src/Telegrator.Localized/Telegrator.Localized.csproj" />
<Project Path="src/Telegrator/Telegrator.csproj" /> <Project Path="src/Telegrator/Telegrator.csproj" />
<Project Path="tests/Telegrator.Tests/Telegrator.Tests.csproj" /> <Project Path="tests/Telegrator.Tests/Telegrator.Tests.csproj" />
@@ -6,3 +6,4 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("Style", "IDE0090")] [assembly: SuppressMessage("Style", "IDE0090")]
[assembly: SuppressMessage("Roslynator", "RCS1037")]
@@ -112,7 +112,7 @@ public class ImplicitHandlerBuilderExtensionsGenerator : IIncrementalGenerator
{ {
try try
{ {
PrimaryConstructorBaseTypeSyntax primaryConstructor = (PrimaryConstructorBaseTypeSyntax)classDeclaration.BaseList.Types.ElementAt(0); PrimaryConstructorBaseTypeSyntax primaryConstructor = (PrimaryConstructorBaseTypeSyntax)classDeclaration.BaseList.Types[0];
MethodDeclarationSyntax genExtension = GeneratedExtensionsMethod(classDeclaration, classDeclaration.ParameterList, primaryConstructor.ArgumentList, targeter); MethodDeclarationSyntax genExtension = GeneratedExtensionsMethod(classDeclaration, classDeclaration.ParameterList, primaryConstructor.ArgumentList, targeter);
extensions.Add(genExtension); extensions.Add(genExtension);
} }
@@ -239,7 +239,7 @@ public class ImplicitHandlerBuilderExtensionsGenerator : IIncrementalGenerator
if (targeters.TryGetValue(classDeclaration.Identifier.ValueText, out MethodDeclarationSyntax targeter)) if (targeters.TryGetValue(classDeclaration.Identifier.ValueText, out MethodDeclarationSyntax targeter))
return targeter; return targeter;
if (classDeclaration.BaseList != null && targeters.TryGetValue(classDeclaration.BaseList.Types.ElementAt(0).Type.ToString(), out targeter)) if (classDeclaration.BaseList != null && targeters.TryGetValue(classDeclaration.BaseList.Types[0].Type.ToString(), out targeter))
return targeter; return targeter;
return null; return null;
@@ -1,7 +1,7 @@
namespace Telegrator.RoslynGenerators.RoslynExtensions namespace Telegrator.RoslynGenerators.RoslynExtensions;
public static class CollectionsExtensions
{ {
public static class CollectionsExtensions
{
public static IEnumerable<TSource> Combine<TSource>(params IEnumerable<TSource>[] collections) public static IEnumerable<TSource> Combine<TSource>(params IEnumerable<TSource>[] collections)
=> collections.SelectMany(x => x); => collections.SelectMany(x => x);
@@ -60,5 +60,4 @@
public static IEnumerable<T> Repeat<T>(this T item, int times) public static IEnumerable<T> Repeat<T>(this T item, int times)
=> Enumerable.Range(0, times).Select(_ => item); => Enumerable.Range(0, times).Select(_ => item);
}
} }
+63 -183
View File
@@ -4,166 +4,12 @@
<name>Telegrator.Hosting.Web</name> <name>Telegrator.Hosting.Web</name>
</assembly> </assembly>
<members> <members>
<member name="T:Telegrator.Hosting.Web.TelegramBotWebHost">
<summary>
Represents a web hosted telegram bot
</summary>
</member>
<member name="P:Telegrator.Hosting.Web.TelegramBotWebHost.Services">
<inheritdoc/>
</member>
<member name="P:Telegrator.Hosting.Web.TelegramBotWebHost.UpdateRouter">
<inheritdoc/>
</member>
<member name="P:Telegrator.Hosting.Web.TelegramBotWebHost.DataSources">
<inheritdoc/>
</member>
<member name="P:Telegrator.Hosting.Web.TelegramBotWebHost.Lifetime">
<summary>
Allows consumers to be notified of application lifetime events.
</summary>
</member>
<member name="P:Telegrator.Hosting.Web.TelegramBotWebHost.Logger">
<summary>
This application's logger
</summary>
</member>
<member name="P:Telegrator.Hosting.Web.TelegramBotWebHost.Properties">
<inheritdoc/>
</member>
<member name="M:Telegrator.Hosting.Web.TelegramBotWebHost.#ctor(Microsoft.AspNetCore.Builder.WebApplicationBuilder)">
<summary>
Initializes a new instance of the <see cref="T:Microsoft.AspNetCore.Builder.WebApplicationBuilder"/> class.
</summary>
<param name="webApplicationBuilder">The proxied instance of host builder.</param>
</member>
<member name="M:Telegrator.Hosting.Web.TelegramBotWebHost.CreateBuilder(Microsoft.AspNetCore.Builder.WebApplicationOptions)">
<summary>
Creates new <see cref="T:Telegrator.Hosting.TelegramBotHostBuilder"/> with default services and webhook update receiving scheme
</summary>
<returns></returns>
</member>
<member name="M:Telegrator.Hosting.Web.TelegramBotWebHost.CreateSlimBuilder(Microsoft.AspNetCore.Builder.WebApplicationOptions)">
<summary>
Creates new SLIM <see cref="T:Telegrator.Hosting.TelegramBotHostBuilder"/> with default services and webhook update receiving scheme
</summary>
<returns></returns>
</member>
<member name="M:Telegrator.Hosting.Web.TelegramBotWebHost.CreateEmptyBuilder(Microsoft.AspNetCore.Builder.WebApplicationOptions)">
<summary>
Creates new EMPTY <see cref="T:Telegrator.Hosting.TelegramBotHostBuilder"/> WITHOUT any services or update receiving schemes
</summary>
<returns></returns>
</member>
<member name="M:Telegrator.Hosting.Web.TelegramBotWebHost.StartAsync(System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:Telegrator.Hosting.Web.TelegramBotWebHost.StopAsync(System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:Telegrator.Hosting.Web.TelegramBotWebHost.CreateApplicationBuilder">
<inheritdoc/>
</member>
<member name="M:Telegrator.Hosting.Web.TelegramBotWebHost.Use(System.Func{Microsoft.AspNetCore.Http.RequestDelegate,Microsoft.AspNetCore.Http.RequestDelegate})">
<inheritdoc/>
</member>
<member name="M:Telegrator.Hosting.Web.TelegramBotWebHost.New">
<inheritdoc/>
</member>
<member name="M:Telegrator.Hosting.Web.TelegramBotWebHost.Build">
<inheritdoc/>
</member>
<member name="M:Telegrator.Hosting.Web.TelegramBotWebHost.DisposeAsync">
<summary>
Disposes the host.
</summary>
</member>
<member name="M:Telegrator.Hosting.Web.TelegramBotWebHost.Dispose">
<summary>
Disposes the host.
</summary>
</member>
<member name="T:Telegrator.Hosting.Web.TelegramBotWebHostBuilder">
<inheritdoc/>
</member>
<member name="P:Telegrator.Hosting.Web.TelegramBotWebHostBuilder.Handlers">
<inheritdoc/>
</member>
<member name="P:Telegrator.Hosting.Web.TelegramBotWebHostBuilder.Configuration">
<inheritdoc/>
</member>
<member name="P:Telegrator.Hosting.Web.TelegramBotWebHostBuilder.Logging">
<inheritdoc/>
</member>
<member name="P:Telegrator.Hosting.Web.TelegramBotWebHostBuilder.Services">
<inheritdoc/>
</member>
<member name="P:Telegrator.Hosting.Web.TelegramBotWebHostBuilder.Environment">
<inheritdoc/>
</member>
<member name="P:Telegrator.Hosting.Web.TelegramBotWebHostBuilder.Properties">
<inheritdoc/>
</member>
<member name="P:Telegrator.Hosting.Web.TelegramBotWebHostBuilder.Metrics">
<inheritdoc/>
</member>
<member name="M:Telegrator.Hosting.Web.TelegramBotWebHostBuilder.#ctor(Microsoft.AspNetCore.Builder.WebApplicationBuilder)">
<summary>
Initializes a new instance of the <see cref="T:Telegrator.Hosting.Web.TelegramBotWebHostBuilder"/> class.
</summary>
<param name="webApplicationBuilder"></param>
</member>
<member name="M:Telegrator.Hosting.Web.TelegramBotWebHostBuilder.#ctor(Microsoft.AspNetCore.Builder.WebApplicationBuilder,Telegrator.Core.IHandlersCollection)">
<summary>
Initializes a new instance of the <see cref="T:Telegrator.Hosting.Web.TelegramBotWebHostBuilder"/> class.
</summary>
<param name="webApplicationBuilder"></param>
<param name="handlers"></param>
</member>
<member name="M:Telegrator.Hosting.Web.TelegramBotWebHostBuilder.Build">
<summary>
Builds the host.
</summary>
<returns></returns>
</member>
<member name="M:Telegrator.Hosting.Web.TelegramBotWebHostBuilder.ConfigureContainer``1(Microsoft.Extensions.DependencyInjection.IServiceProviderFactory{``0},System.Action{``0})">
<inheritdoc/>
</member>
<member name="T:Telegrator.Hosting.Web.WebhookerOptions">
<summary>
Configuration options for Telegram bot behavior and execution settings.
Controls various aspects of bot operation including concurrency, routing, webhook receiving, and execution policies.
</summary>
</member>
<member name="P:Telegrator.Hosting.Web.WebhookerOptions.WebhookUri">
<summary>
Gets or sets HTTPS URL to send updates to. Use an empty string to remove webhook integration
</summary>
</member>
<member name="P:Telegrator.Hosting.Web.WebhookerOptions.SecretToken">
<summary>
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.
</summary>
</member>
<member name="P:Telegrator.Hosting.Web.WebhookerOptions.MaxConnections">
<summary>
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.
</summary>
</member>
<member name="P:Telegrator.Hosting.Web.WebhookerOptions.DropPendingUpdates">
<summary>
Pass true to drop all pending updates
</summary>
</member>
<member name="T:Telegrator.Mediation.HostedUpdateWebhooker"> <member name="T:Telegrator.Mediation.HostedUpdateWebhooker">
<summary> <summary>
Service for receiving updates for Hosted telegram bots via Webhooks Service for receiving updates for Hosted telegram bots via Webhooks and queuing them to router
</summary> </summary>
</member> </member>
<member name="M:Telegrator.Mediation.HostedUpdateWebhooker.#ctor(Telegram.Bot.ITelegramBotClient,Telegrator.Core.IUpdateRouter,Microsoft.Extensions.Options.IOptions{Telegrator.Hosting.Web.WebhookerOptions})"> <member name="M:Telegrator.Mediation.HostedUpdateWebhooker.#ctor(Telegram.Bot.ITelegramBotClient,Telegrator.Core.IUpdateRouter,Microsoft.Extensions.Options.IOptions{Telegrator.WebhookerOptions})">
<summary> <summary>
Initiallizes new instance of <see cref="T:Telegrator.Mediation.HostedUpdateWebhooker"/> Initiallizes new instance of <see cref="T:Telegrator.Mediation.HostedUpdateWebhooker"/>
</summary> </summary>
@@ -194,36 +40,41 @@
</summary> </summary>
<param name="routeBuilder"></param> <param name="routeBuilder"></param>
</member> </member>
<member name="T:Telegrator.ServicesCollectionExtensions"> <member name="T:Telegrator.WebHostBuilderExtensions">
<summary>
Provides extension methods for <see cref="T:Microsoft.Extensions.Hosting.IHostApplicationBuilder"/> to configure Telegrator.
</summary>
</member>
<member name="M:Telegrator.WebHostBuilderExtensions.AddTelegratorWeb(Microsoft.Extensions.Hosting.IHostApplicationBuilder,Telegrator.TelegratorOptions,Telegrator.Core.IHandlersCollection)">
<summary>
Replaces TelegramBotWebHostBuilder. Configures DI, options, and handlers.
</summary>
</member>
<member name="M:Telegrator.WebHostBuilderExtensions.AddTelegratorWeb(Microsoft.Extensions.Hosting.IHostApplicationBuilder,Telegrator.TelegratorOptions,Telegrator.Core.IHandlersCollection,System.Action{Telegrator.Hosting.ITelegramBotHostBuilder})">
<summary>
Replaces TelegramBotWebHostBuilder. Configures DI, options, and handlers.
</summary>
</member>
<member name="M:Telegrator.WebHostBuilderExtensions.AddTelegratorWebInternal(Microsoft.Extensions.DependencyInjection.IServiceCollection,Microsoft.Extensions.Configuration.IConfiguration,System.Collections.Generic.IDictionary{System.Object,System.Object},Telegrator.Core.IHandlersCollection@,Telegrator.TelegratorOptions)">
<summary>
Replaces TelegramBotWebHostBuilder. Configures DI, options, and handlers.
</summary>
</member>
<member name="T:Telegrator.WebServicesCollectionExtensions">
<summary> <summary>
Contains extensions for <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection"/> Contains extensions for <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection"/>
Provides method to configure Telegram Bot WebHost Provides method to configure Telegram Bot WebHost
</summary> </summary>
</member> </member>
<member name="F:Telegrator.ServicesCollectionExtensions.HandlersCollectionPropertyKey"> <member name="M:Telegrator.WebServicesCollectionExtensions.ConfigureWebhooker(Microsoft.Extensions.DependencyInjection.IServiceCollection,Telegrator.WebhookerOptions)">
<summary> <summary>
The key used to store the <see cref="T:Telegrator.Core.IHandlersCollection"/> in the builder properties. Adds WebhookerOptions to services
</summary> </summary>
<param name="services"></param>
<param name="options"></param>
<returns></returns>
</member> </member>
<member name="M:Telegrator.ServicesCollectionExtensions.get_Handlers(Microsoft.AspNetCore.Builder.WebApplicationBuilder)"> <member name="M:Telegrator.WebServicesCollectionExtensions.TryFindWebhooker(System.IServiceProvider,Telegrator.Mediation.HostedUpdateWebhooker@)">
<inheritdoc cref="P:Telegrator.ServicesCollectionExtensions.&lt;G&gt;$41F16C2D39AF52899E745C9C9F42FF83.Handlers"/>
</member>
<member name="M:Telegrator.ServicesCollectionExtensions.AddTelegratorWeb(Telegrator.Hosting.ITelegramBotHostBuilder,Telegrator.TelegratorOptions,Telegrator.Core.IHandlersCollection,System.Action{Telegrator.Hosting.ITelegramBotHostBuilder})">
<summary>
Replaces TelegramBotWebHostBuilder. Configures DI, options, and handlers.
</summary>
</member>
<member name="M:Telegrator.ServicesCollectionExtensions.AddTelegratorWeb(Microsoft.AspNetCore.Builder.WebApplicationBuilder,Telegrator.TelegratorOptions,Telegrator.Core.IHandlersCollection,System.Action{Telegrator.Hosting.ITelegramBotHostBuilder})">
<summary>
Replaces TelegramBotWebHostBuilder. Configures DI, options, and handlers.
</summary>
</member>
<member name="M:Telegrator.ServicesCollectionExtensions.AddTelegratorWebInternal(Microsoft.Extensions.DependencyInjection.IServiceCollection,Microsoft.Extensions.Configuration.IConfiguration,System.Collections.Generic.IDictionary{System.Object,System.Object},Telegrator.Core.IHandlersCollection@,Telegrator.TelegratorOptions)">
<summary>
Replaces TelegramBotWebHostBuilder. Configures DI, options, and handlers.
</summary>
</member>
<member name="M:Telegrator.ServicesCollectionExtensions.TryFindWebhooker(System.IServiceProvider,Telegrator.Mediation.HostedUpdateWebhooker@)">
<summary> <summary>
Searchs for <see cref="T:Telegrator.Mediation.HostedUpdateWebhooker"/> hosted service inside hosts services Searchs for <see cref="T:Telegrator.Mediation.HostedUpdateWebhooker"/> hosted service inside hosts services
</summary> </summary>
@@ -231,13 +82,18 @@
<param name="webhooker"></param> <param name="webhooker"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Telegrator.ServicesCollectionExtensions.UseTelegratorWeb``1(``0,System.Boolean)"> <member name="T:Telegrator.WebTelegramBotHostExtensions">
<summary>
Provides useful methods to adjust Telegram bot Host
</summary>
</member>
<member name="M:Telegrator.WebTelegramBotHostExtensions.UseTelegratorWeb``1(``0,System.Boolean)">
<summary> <summary>
Replaces the initialization logic from TelegramBotWebHost constructor. Replaces the initialization logic from TelegramBotWebHost constructor.
Initializes the bot and logs handlers on application startup. Initializes the bot and logs handlers on application startup.
</summary> </summary>
</member> </member>
<member name="M:Telegrator.ServicesCollectionExtensions.RemapWebhook``1(``0,System.String)"> <member name="M:Telegrator.WebTelegramBotHostExtensions.RemapWebhook``1(``0,System.String)">
<summary> <summary>
Allows to remap receiving webhook endpoint and map new route to webhost. Allows to remap receiving webhook endpoint and map new route to webhost.
</summary> </summary>
@@ -246,16 +102,40 @@
<returns></returns> <returns></returns>
<exception cref="T:System.ArgumentException"></exception> <exception cref="T:System.ArgumentException"></exception>
</member> </member>
<member name="M:Telegrator.ServicesCollectionExtensions.AddTelegramWebhook(Microsoft.Extensions.DependencyInjection.IServiceCollection)"> <member name="M:Telegrator.WebTelegramBotHostExtensions.AddTelegramWebhook(Microsoft.Extensions.DependencyInjection.IServiceCollection)">
<summary> <summary>
Registers <see cref="T:Telegram.Bot.ITelegramBotClient"/> service with <see cref="T:Telegrator.Mediation.HostedUpdateWebhooker"/> to receive updates using webhook Registers <see cref="T:Telegram.Bot.ITelegramBotClient"/> service with <see cref="T:Telegrator.Mediation.HostedUpdateWebhooker"/> to receive updates using webhook
</summary> </summary>
<param name="services"></param> <param name="services"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="P:Telegrator.ServicesCollectionExtensions.&lt;G&gt;$41F16C2D39AF52899E745C9C9F42FF83.Handlers"> <member name="T:Telegrator.WebhookerOptions">
<summary> <summary>
Gets the <see cref="T:Telegrator.Core.IHandlersCollection"/> from the builder properties. Configuration options for Telegram bot behavior and execution settings.
Controls various aspects of bot operation including concurrency, routing, webhook receiving, and execution policies.
</summary>
</member>
<member name="P:Telegrator.WebhookerOptions.WebhookUri">
<summary>
Gets or sets HTTPS URL to send updates to. Use an empty string to remove webhook integration
</summary>
</member>
<member name="P:Telegrator.WebhookerOptions.SecretToken">
<summary>
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.
</summary>
</member>
<member name="P:Telegrator.WebhookerOptions.MaxConnections">
<summary>
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.
</summary>
</member>
<member name="P:Telegrator.WebhookerOptions.DropPendingUpdates">
<summary>
Pass true to drop all pending updates
</summary> </summary>
</member> </member>
</members> </members>
+205
View File
@@ -0,0 +1,205 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Telegrator.Hosting.WideBot</name>
</assembly>
<members>
<member name="T:Telegrator.Mediation.HostedWideBotUpdateReceiver">
<summary>
Service for receiving updates for Hosted wide telegram bots and queuing them to router
</summary>
<param name="logger"></param>
<param name="botClient"></param>
<param name="updateRouter"></param>
<param name="options"></param>
</member>
<member name="M:Telegrator.Mediation.HostedWideBotUpdateReceiver.#ctor(Microsoft.Extensions.Logging.ILogger{Telegrator.Mediation.HostedWideBotUpdateReceiver},Telegram.Bot.ITelegramBotClient,Telegrator.Core.IUpdateRouter,Microsoft.Extensions.Options.IOptions{Telegrator.WideBotOptions})">
<summary>
Service for receiving updates for Hosted wide telegram bots and queuing them to router
</summary>
<param name="logger"></param>
<param name="botClient"></param>
<param name="updateRouter"></param>
<param name="options"></param>
</member>
<member name="M:Telegrator.Mediation.HostedWideBotUpdateReceiver.ExecuteAsync(System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="T:Telegrator.Mediation.WideUpdateReceiver">
<summary>
Reactive implementation of <see cref="T:Telegrator.Core.IUpdateReceiver"/> for polling updates from Telegram.
Provides custom update receiving logic with error handling and configuration options.
</summary>
<param name="client">The Telegram bot client for making API requests.</param>
</member>
<member name="M:Telegrator.Mediation.WideUpdateReceiver.#ctor(Telegram.Bot.WTelegramBotClient)">
<summary>
Reactive implementation of <see cref="T:Telegrator.Core.IUpdateReceiver"/> for polling updates from Telegram.
Provides custom update receiving logic with error handling and configuration options.
</summary>
<param name="client">The Telegram bot client for making API requests.</param>
</member>
<member name="M:Telegrator.Mediation.WideUpdateReceiver.ReceiveAsync(Telegram.Bot.Polling.IUpdateHandler,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="T:Telegrator.TelegratorWClient">
<summary>
Client class for the Telegrator library with Wider functionality, provided by WTelegramBotClient.
Extends TelegramBotClient with reactive capabilities for handling updates.
</summary>
</member>
<member name="P:Telegrator.TelegratorWClient.Options">
<inheritdoc/>
</member>
<member name="P:Telegrator.TelegratorWClient.Handlers">
<inheritdoc/>
</member>
<member name="P:Telegrator.TelegratorWClient.BotInfo">
<inheritdoc/>
</member>
<member name="P:Telegrator.TelegratorWClient.UpdateRouter">
<inheritdoc/>
</member>
<member name="M:Telegrator.TelegratorWClient.#ctor(Telegram.Bot.WTelegramBotClientOptions,Telegrator.TelegratorOptions,System.Net.Http.HttpClient,System.Threading.CancellationToken)">
<summary>
Initializes new instance of <see cref="T:Telegrator.TelegratorWClient"/>
</summary>
<param name="wOptions"></param>
<param name="telegratorOptions"></param>
<param name="httpClient"></param>
<param name="cancellationToken"></param>
</member>
<member name="M:Telegrator.TelegratorWClient.StartReceiving(Telegram.Bot.Polling.ReceiverOptions,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:Telegrator.TelegratorWClient.StartReceivingAsync(Telegram.Bot.Polling.ReceiverOptions,System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="T:Telegrator.HandlersExtensions">
<summary>
Provides extensions memebrs for <see cref="T:Telegrator.Core.Handlers.UpdateHandlerBase"/> for easy access to Wider bot functions and update
</summary>
</member>
<member name="M:Telegrator.HandlersExtensions.get_WClient``1(Telegrator.Core.Handlers.AbstractUpdateHandler{``0})">
<inheritdoc cref="P:Telegrator.HandlersExtensions.&lt;G&gt;$F89AF16C011F73161937A1614DCDDD7A`1.WClient"/>
</member>
<member name="M:Telegrator.HandlersExtensions.get_WideUpdate``1(Telegrator.Core.Handlers.AbstractUpdateHandler{``0})">
<inheritdoc cref="P:Telegrator.HandlersExtensions.&lt;G&gt;$F89AF16C011F73161937A1614DCDDD7A`1.WideUpdate"/>
</member>
<member name="M:Telegrator.HandlersExtensions.get_TLUpdate``1(Telegrator.Core.Handlers.AbstractUpdateHandler{``0})">
<inheritdoc cref="P:Telegrator.HandlersExtensions.&lt;G&gt;$F89AF16C011F73161937A1614DCDDD7A`1.TLUpdate"/>
</member>
<member name="M:Telegrator.HandlersExtensions.AsWClient(Telegram.Bot.ITelegramBotClient)">
<summary>
Casts Update to <see cref="T:Telegram.Bot.WTelegramBotClient"/>
</summary>
</member>
<member name="M:Telegrator.HandlersExtensions.AsWUpdate(Telegram.Bot.Types.Update)">
<summary>
Casts Update to <see cref="T:WTelegram.Types.Update"/>
</summary>
</member>
<member name="P:Telegrator.HandlersExtensions.&lt;G&gt;$F89AF16C011F73161937A1614DCDDD7A`1.WClient">
<summary>
Casts Update to <see cref="T:Telegram.Bot.WTelegramBotClient"/>
</summary>
</member>
<member name="P:Telegrator.HandlersExtensions.&lt;G&gt;$F89AF16C011F73161937A1614DCDDD7A`1.WideUpdate">
<summary>
Casts Update to <see cref="T:WTelegram.Types.Update"/>
</summary>
</member>
<member name="P:Telegrator.HandlersExtensions.&lt;G&gt;$F89AF16C011F73161937A1614DCDDD7A`1.TLUpdate">
<summary>
Casts Update to <see cref="T:TL.Update"/>
</summary>
</member>
<member name="T:Telegrator.WideHostBuilderExtensions">
<summary>
Provides extension methods for <see cref="T:Microsoft.Extensions.Hosting.IHostApplicationBuilder"/> to configure Telegrator.
</summary>
</member>
<member name="M:Telegrator.WideHostBuilderExtensions.AddWideTelegrator(Microsoft.Extensions.Hosting.IHostApplicationBuilder,System.Func{System.IServiceProvider,System.Data.Common.DbConnection},System.Action{Telegrator.Hosting.ITelegramBotHostBuilder},Telegrator.TelegratorOptions,Telegrator.Core.IHandlersCollection)">
<summary>
Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
</summary>
</member>
<member name="M:Telegrator.WideHostBuilderExtensions.AddWideTelegrator(Microsoft.Extensions.Hosting.IHostApplicationBuilder,System.Func{System.IServiceProvider,System.Data.Common.DbConnection},Telegrator.TelegratorOptions,Telegrator.Core.IHandlersCollection)">
<summary>
Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
</summary>
</member>
<member name="M:Telegrator.WideHostBuilderExtensions.AddWideTelegratorInternal(Microsoft.Extensions.DependencyInjection.IServiceCollection,Microsoft.Extensions.Configuration.IConfiguration,System.Collections.Generic.IDictionary{System.Object,System.Object},System.Func{System.IServiceProvider,System.Data.Common.DbConnection},Telegrator.Core.IHandlersCollection@,Telegrator.TelegratorOptions)">
<summary>
Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
</summary>
</member>
<member name="T:Telegrator.WideBotServiceCollectionExtensions">
<summary>
Contains extensions for <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection"/>
Provides method to configure Telegram Bot WebHost
</summary>
</member>
<member name="M:Telegrator.WideBotServiceCollectionExtensions.ConfigureWideTelegram(Microsoft.Extensions.DependencyInjection.IServiceCollection,Telegram.Bot.WTelegramBotClientOptions)">
<summary>
Adds WTelegramBotClientOptions to services
</summary>
<param name="services"></param>
<param name="options"></param>
<returns></returns>
</member>
<member name="M:Telegrator.WideBotServiceCollectionExtensions.ConfigureWideBot(Microsoft.Extensions.DependencyInjection.IServiceCollection,Telegrator.WideBotOptions)">
<summary>
Adds WTelegramBotClientOptions to services
</summary>
<param name="services"></param>
<param name="options"></param>
<returns></returns>
</member>
<member name="M:Telegrator.WideBotServiceCollectionExtensions.AddMTProtoUpdateReceiver(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Boolean)">
<summary>
Adds WTelegramBotClient
</summary>
<param name="services"></param>
<param name="useHttp"></param>
<returns></returns>
</member>
<member name="T:Telegrator.WideTelegramBotHostExtensions">
<summary>
Provides useful methods to adjust Telegram bot Host
</summary>
</member>
<member name="M:Telegrator.WideTelegramBotHostExtensions.UseWideTelegrator(Microsoft.Extensions.Hosting.IHost)">
<summary>
Replaces the initialization logic from TelegramBotWebHost constructor.
Initializes the bot and logs handlers on application startup.
</summary>
</member>
<member name="T:Telegrator.WideBotOptions">
<summary>
Represents configuration options for initializing and customizing the behavior of a WideBot instance.
</summary>
<remarks>Use this class to specify required API credentials, optional proxy settings, update handling
preferences, and SQL command detection for WideBot. All required properties must be set before using the options
with a WideBot instance.
</remarks>
</member>
<member name="P:Telegrator.WideBotOptions.ApiId">
<inheritdoc cref="P:Telegram.Bot.WTelegramBotClientOptions.ApiId"/>
</member>
<member name="P:Telegrator.WideBotOptions.ApiHash">
<inheritdoc cref="P:Telegram.Bot.WTelegramBotClientOptions.ApiHash"/>
</member>
<member name="P:Telegrator.WideBotOptions.MTProxy">
<inheritdoc cref="P:Telegram.Bot.WTelegramBotClientOptions.MTProxy"/>
</member>
<member name="P:Telegrator.WideBotOptions.SqlCommands">
<inheritdoc cref="P:Telegram.Bot.WTelegramBotClientOptions.SqlCommands"/>
</member>
<member name="P:Telegrator.WideBotOptions.DropPendingUpdates">
<summary>
Gets or sets a value indicating whether pending updates should be discarded.
</summary>
</member>
</members>
</doc>
+41 -88
View File
@@ -40,63 +40,6 @@
Represents a hosted telegram bots and services builder that helps manage configuration, logging, lifetime, and more. Represents a hosted telegram bots and services builder that helps manage configuration, logging, lifetime, and more.
</summary> </summary>
</member> </member>
<member name="T:Telegrator.Hosting.TelegramBotHost">
<summary>
Represents a hosted telegram bot
</summary>
</member>
<member name="P:Telegrator.Hosting.TelegramBotHost.Services">
<inheritdoc/>
</member>
<member name="P:Telegrator.Hosting.TelegramBotHost.UpdateRouter">
<inheritdoc/>
</member>
<member name="P:Telegrator.Hosting.TelegramBotHost.Logger">
<summary>
This application's logger
</summary>
</member>
<member name="M:Telegrator.Hosting.TelegramBotHost.#ctor(Microsoft.Extensions.Hosting.HostApplicationBuilder)">
<summary>
Initializes a new instance of the <see cref="T:Telegrator.Hosting.TelegramBotHost"/> class.
</summary>
<param name="hostApplicationBuilder">The proxied instance of host builder.</param>
</member>
<member name="M:Telegrator.Hosting.TelegramBotHost.CreateBuilder">
<summary>
Creates new <see cref="T:Telegrator.Hosting.TelegramBotHostBuilder"/> with default configuration, services and long-polling update receiving scheme
</summary>
<returns></returns>
</member>
<member name="M:Telegrator.Hosting.TelegramBotHost.CreateBuilder(Microsoft.Extensions.Hosting.HostApplicationBuilderSettings)">
<summary>
Creates new <see cref="T:Telegrator.Hosting.TelegramBotHostBuilder"/> with default services and long-polling update receiving scheme
</summary>
<returns></returns>
</member>
<member name="M:Telegrator.Hosting.TelegramBotHost.CreateEmptyBuilder">
<summary>
Creates new EMPTY <see cref="T:Telegrator.Hosting.TelegramBotHostBuilder"/> WITHOUT any services or update receiving schemes
</summary>
<returns></returns>
</member>
<member name="M:Telegrator.Hosting.TelegramBotHost.CreateEmptyBuilder(Microsoft.Extensions.Hosting.HostApplicationBuilderSettings)">
<summary>
Creates new EMPTY <see cref="T:Telegrator.Hosting.TelegramBotHostBuilder"/> WITHOUT any services or update receiving schemes
</summary>
<returns></returns>
</member>
<member name="M:Telegrator.Hosting.TelegramBotHost.StartAsync(System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:Telegrator.Hosting.TelegramBotHost.StopAsync(System.Threading.CancellationToken)">
<inheritdoc/>
</member>
<member name="M:Telegrator.Hosting.TelegramBotHost.Dispose">
<summary>
Disposes the host.
</summary>
</member>
<member name="T:Telegrator.Hosting.TelegramBotHostBuilder"> <member name="T:Telegrator.Hosting.TelegramBotHostBuilder">
<inheritdoc/> <inheritdoc/>
</member> </member>
@@ -121,25 +64,19 @@
<member name="P:Telegrator.Hosting.TelegramBotHostBuilder.Metrics"> <member name="P:Telegrator.Hosting.TelegramBotHostBuilder.Metrics">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="M:Telegrator.Hosting.TelegramBotHostBuilder.#ctor(Microsoft.Extensions.Hosting.HostApplicationBuilder)"> <member name="M:Telegrator.Hosting.TelegramBotHostBuilder.#ctor(Microsoft.Extensions.Hosting.IHostApplicationBuilder)">
<summary> <summary>
Initializes a new instance of the <see cref="T:Telegrator.Hosting.TelegramBotHostBuilder"/> class. Initializes a new instance of the <see cref="T:Telegrator.Hosting.TelegramBotHostBuilder"/> class.
</summary> </summary>
<param name="hostApplicationBuilder"></param> <param name="hostApplicationBuilder"></param>
</member> </member>
<member name="M:Telegrator.Hosting.TelegramBotHostBuilder.#ctor(Microsoft.Extensions.Hosting.HostApplicationBuilder,Telegrator.Core.IHandlersCollection)"> <member name="M:Telegrator.Hosting.TelegramBotHostBuilder.#ctor(Microsoft.Extensions.Hosting.IHostApplicationBuilder,Telegrator.Core.IHandlersCollection)">
<summary> <summary>
Initializes a new instance of the <see cref="T:Telegrator.Hosting.TelegramBotHostBuilder"/> class. Initializes a new instance of the <see cref="T:Telegrator.Hosting.TelegramBotHostBuilder"/> class.
</summary> </summary>
<param name="hostApplicationBuilder"></param> <param name="hostApplicationBuilder"></param>
<param name="handlers"></param> <param name="handlers"></param>
</member> </member>
<member name="M:Telegrator.Hosting.TelegramBotHostBuilder.Build">
<summary>
Builds the host.
</summary>
<returns></returns>
</member>
<member name="M:Telegrator.Hosting.TelegramBotHostBuilder.ConfigureContainer``1(Microsoft.Extensions.DependencyInjection.IServiceProviderFactory{``0},System.Action{``0})"> <member name="M:Telegrator.Hosting.TelegramBotHostBuilder.ConfigureContainer``1(Microsoft.Extensions.DependencyInjection.IServiceProviderFactory{``0},System.Action{``0})">
<inheritdoc/> <inheritdoc/>
</member> </member>
@@ -158,42 +95,42 @@
<member name="M:Telegrator.Logging.MicrosoftLoggingAdapter.Log(Telegrator.Logging.LogLevel,System.String,System.Exception)"> <member name="M:Telegrator.Logging.MicrosoftLoggingAdapter.Log(Telegrator.Logging.LogLevel,System.String,System.Exception)">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="T:Telegrator.Polling.HostedUpdateReceiver"> <member name="T:Telegrator.Mediation.HostedUpdateReceiver">
<summary> <summary>
Service for receiving updates for Hosted telegram bots Service for receiving updates for Hosted telegram botsand queuing them to router
</summary> </summary>
<param name="botClient"></param> <param name="botClient"></param>
<param name="updateRouter"></param> <param name="updateRouter"></param>
<param name="options"></param> <param name="options"></param>
<param name="logger"></param> <param name="logger"></param>
</member> </member>
<member name="M:Telegrator.Polling.HostedUpdateReceiver.#ctor(Telegram.Bot.ITelegramBotClient,Telegrator.Core.IUpdateRouter,Microsoft.Extensions.Options.IOptions{Telegram.Bot.Polling.ReceiverOptions},Microsoft.Extensions.Logging.ILogger{Telegrator.Polling.HostedUpdateReceiver})"> <member name="M:Telegrator.Mediation.HostedUpdateReceiver.#ctor(Telegram.Bot.ITelegramBotClient,Telegrator.Core.IUpdateRouter,Microsoft.Extensions.Options.IOptions{Telegram.Bot.Polling.ReceiverOptions},Microsoft.Extensions.Logging.ILogger{Telegrator.Mediation.HostedUpdateReceiver})">
<summary> <summary>
Service for receiving updates for Hosted telegram bots Service for receiving updates for Hosted telegram botsand queuing them to router
</summary> </summary>
<param name="botClient"></param> <param name="botClient"></param>
<param name="updateRouter"></param> <param name="updateRouter"></param>
<param name="options"></param> <param name="options"></param>
<param name="logger"></param> <param name="logger"></param>
</member> </member>
<member name="M:Telegrator.Polling.HostedUpdateReceiver.ExecuteAsync(System.Threading.CancellationToken)"> <member name="M:Telegrator.Mediation.HostedUpdateReceiver.ExecuteAsync(System.Threading.CancellationToken)">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="T:Telegrator.Polling.HostUpdateRouter"> <member name="T:Telegrator.Mediation.HostUpdateRouter">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="F:Telegrator.Polling.HostUpdateRouter.Logger"> <member name="F:Telegrator.Mediation.HostUpdateRouter.Logger">
<summary> <summary>
<see cref="T:Microsoft.Extensions.Logging.ILogger"/> of this router <see cref="T:Microsoft.Extensions.Logging.ILogger"/> of this router
</summary> </summary>
</member> </member>
<member name="M:Telegrator.Polling.HostUpdateRouter.#ctor(Telegrator.Core.IHandlersProvider,Telegrator.Core.IAwaitingProvider,Telegrator.Core.States.IStateStorage,Microsoft.Extensions.Options.IOptions{Telegrator.TelegratorOptions},Telegrator.Core.ITelegramBotInfo,Microsoft.Extensions.Logging.ILogger{Telegrator.Polling.HostUpdateRouter})"> <member name="M:Telegrator.Mediation.HostUpdateRouter.#ctor(Telegrator.Core.IHandlersProvider,Telegrator.Core.IAwaitingProvider,Telegrator.Core.States.IStateStorage,Microsoft.Extensions.Options.IOptions{Telegrator.TelegratorOptions},Telegrator.Core.ITelegramBotInfo,Microsoft.Extensions.Logging.ILogger{Telegrator.Mediation.HostUpdateRouter})">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="M:Telegrator.Polling.HostUpdateRouter.HandleUpdateAsync(Telegram.Bot.ITelegramBotClient,Telegram.Bot.Types.Update,System.Threading.CancellationToken)"> <member name="M:Telegrator.Mediation.HostUpdateRouter.HandleUpdateAsync(Telegram.Bot.ITelegramBotClient,Telegram.Bot.Types.Update,System.Threading.CancellationToken)">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="M:Telegrator.Polling.HostUpdateRouter.HandleException(Telegram.Bot.ITelegramBotClient,System.Exception,Telegram.Bot.Polling.HandleErrorSource,System.Threading.CancellationToken)"> <member name="M:Telegrator.Mediation.HostUpdateRouter.HandleException(Telegram.Bot.ITelegramBotClient,System.Exception,Telegram.Bot.Polling.HandleErrorSource,System.Threading.CancellationToken)">
<summary> <summary>
Default exception handler of this router Default exception handler of this router
</summary> </summary>
@@ -239,12 +176,7 @@
The key used to store the <see cref="T:Telegrator.Core.IHandlersCollection"/> in the builder properties. The key used to store the <see cref="T:Telegrator.Core.IHandlersCollection"/> in the builder properties.
</summary> </summary>
</member> </member>
<member name="M:Telegrator.HostBuilderExtensions.AddTelegrator(Telegrator.Hosting.ITelegramBotHostBuilder,Telegrator.TelegratorOptions,Telegrator.Core.IHandlersCollection,System.Action{Telegrator.Hosting.ITelegramBotHostBuilder})"> <member name="M:Telegrator.HostBuilderExtensions.AddTelegrator(Microsoft.Extensions.Hosting.IHostApplicationBuilder,Telegrator.TelegratorOptions,Telegrator.Core.IHandlersCollection,System.Action{Telegrator.Hosting.ITelegramBotHostBuilder})">
<summary>
Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
</summary>
</member>
<member name="M:Telegrator.HostBuilderExtensions.AddTelegrator(Microsoft.Extensions.Hosting.HostApplicationBuilder,Telegrator.TelegratorOptions,Telegrator.Core.IHandlersCollection,System.Action{Telegrator.Hosting.ITelegramBotHostBuilder})">
<summary> <summary>
Replaces TelegramBotHostBuilder. Configures DI, options, and handlers. Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
</summary> </summary>
@@ -259,18 +191,39 @@
Replaces TelegramBotHostBuilder. Configures DI, options, and handlers. Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
</summary> </summary>
</member> </member>
<member name="M:Telegrator.HostBuilderExtensions.AddTelegrator(Microsoft.Extensions.Hosting.IHostBuilder,Telegrator.TelegratorOptions,Telegrator.Core.IHandlersCollection,System.Action{Telegrator.Core.IHandlersCollection})">
<summary>
Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
</summary>
</member>
<member name="M:Telegrator.HostBuilderExtensions.AddTelegratorInternal(Microsoft.Extensions.DependencyInjection.IServiceCollection,Microsoft.Extensions.Configuration.IConfiguration,System.Collections.Generic.IDictionary{System.Object,System.Object},Telegrator.Core.IHandlersCollection@,Telegrator.TelegratorOptions)"> <member name="M:Telegrator.HostBuilderExtensions.AddTelegratorInternal(Microsoft.Extensions.DependencyInjection.IServiceCollection,Microsoft.Extensions.Configuration.IConfiguration,System.Collections.Generic.IDictionary{System.Object,System.Object},Telegrator.Core.IHandlersCollection@,Telegrator.TelegratorOptions)">
<summary> <summary>
Replaces TelegramBotHostBuilder. Configures DI, options, and handlers. Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
</summary> </summary>
</member> </member>
<member name="T:Telegrator.ServicesCollectionExtensions"> <member name="T:Telegrator.HostServicesCollectionExtensions">
<summary> <summary>
Contains extensions for <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection"/> Contains extensions for <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection"/>
Provides method to configure Telegram Bot Host Provides method to configure Telegram Bot Host
</summary> </summary>
</member> </member>
<member name="M:Telegrator.ServicesCollectionExtensions.AddStateStorage``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)"> <member name="M:Telegrator.HostServicesCollectionExtensions.ConfigureTelegram(Microsoft.Extensions.DependencyInjection.IServiceCollection,Telegram.Bot.TelegramBotClientOptions)">
<summary>
Adds TelegramBotClientOptions to services
</summary>
<param name="services"></param>
<param name="options"></param>
<returns></returns>
</member>
<member name="M:Telegrator.HostServicesCollectionExtensions.ConfigureReceiver(Microsoft.Extensions.DependencyInjection.IServiceCollection,Telegram.Bot.Polling.ReceiverOptions)">
<summary>
Adds ReceiverOptions to services
</summary>
<param name="services"></param>
<param name="options"></param>
<returns></returns>
</member>
<member name="M:Telegrator.HostServicesCollectionExtensions.AddStateStorage``1(Microsoft.Extensions.DependencyInjection.IServiceCollection)">
<summary> <summary>
Registers <see cref="T:Telegrator.Core.States.IStateStorage"/> service Registers <see cref="T:Telegrator.Core.States.IStateStorage"/> service
</summary> </summary>
@@ -278,21 +231,21 @@
<param name="services"></param> <param name="services"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Telegrator.ServicesCollectionExtensions.AddTelegramBotHostDefaults(Microsoft.Extensions.DependencyInjection.IServiceCollection)"> <member name="M:Telegrator.HostServicesCollectionExtensions.AddTelegramBotHostDefaults(Microsoft.Extensions.DependencyInjection.IServiceCollection)">
<summary> <summary>
Registers <see cref="T:Telegrator.Hosting.TelegramBotHost"/> default services Registers <see cref="N:Telegrator"/> default services
</summary> </summary>
<param name="services"></param> <param name="services"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Telegrator.ServicesCollectionExtensions.AddTelegramReceiver(Microsoft.Extensions.DependencyInjection.IServiceCollection)"> <member name="M:Telegrator.HostServicesCollectionExtensions.AddTelegramReceiver(Microsoft.Extensions.DependencyInjection.IServiceCollection)">
<summary> <summary>
Registers <see cref="T:Telegram.Bot.ITelegramBotClient"/> service with <see cref="T:Telegrator.Polling.HostedUpdateReceiver"/> to receive updates using long polling Registers <see cref="T:Telegram.Bot.ITelegramBotClient"/> service with <see cref="T:Telegrator.Mediation.HostedUpdateReceiver"/> to receive updates using long polling
</summary> </summary>
<param name="services"></param> <param name="services"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Telegrator.ServicesCollectionExtensions.TypedTelegramBotClientFactory(System.Net.Http.HttpClient,System.IServiceProvider)"> <member name="M:Telegrator.HostServicesCollectionExtensions.TypedTelegramBotClientFactory(System.Net.Http.HttpClient,System.IServiceProvider)">
<summary> <summary>
<see cref="T:Telegram.Bot.ITelegramBotClient"/> factory method <see cref="T:Telegram.Bot.ITelegramBotClient"/> factory method
</summary> </summary>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Telegrator.Localized</name>
</assembly>
<members>
</members>
</doc>
+46 -14
View File
@@ -5483,6 +5483,14 @@
Gets the update router for handling incoming updates. Gets the update router for handling incoming updates.
</summary> </summary>
</member> </member>
<member name="M:Telegrator.ITelegratorBot.StartReceivingAsync(Telegram.Bot.Polling.ReceiverOptions,System.Threading.CancellationToken)">
<summary>
Initializes the update router and begins polling for updates asynchronously.
</summary>
<param name="receiverOptions">Optional receiver options for configuring update polling.</param>
<param name="cancellationToken">The cancellation token to stop receiving updates.</param>
<returns></returns>
</member>
<member name="T:Telegrator.Logging.ConsoleLogger"> <member name="T:Telegrator.Logging.ConsoleLogger">
<summary> <summary>
Console logger implementation that writes to System.Console. Console logger implementation that writes to System.Console.
@@ -6027,6 +6035,9 @@
Manages the distribution of updates between regular handlers and awaiting handlers. Manages the distribution of updates between regular handlers and awaiting handlers.
</summary> </summary>
</member> </member>
<member name="P:Telegrator.Mediation.UpdateRouter.Options">
<inheritdoc/>
</member>
<member name="P:Telegrator.Mediation.UpdateRouter.HandlersProvider"> <member name="P:Telegrator.Mediation.UpdateRouter.HandlersProvider">
<inheritdoc/> <inheritdoc/>
</member> </member>
@@ -6036,9 +6047,6 @@
<member name="P:Telegrator.Mediation.UpdateRouter.StateStorage"> <member name="P:Telegrator.Mediation.UpdateRouter.StateStorage">
<inheritdoc/> <inheritdoc/>
</member> </member>
<member name="P:Telegrator.Mediation.UpdateRouter.Options">
<inheritdoc/>
</member>
<member name="P:Telegrator.Mediation.UpdateRouter.HandlersPool"> <member name="P:Telegrator.Mediation.UpdateRouter.HandlersPool">
<inheritdoc/> <inheritdoc/>
</member> </member>
@@ -6377,14 +6385,14 @@
Represents handler results, allowing to communicate with router and control aspect execution Represents handler results, allowing to communicate with router and control aspect execution
</summary> </summary>
</member> </member>
<member name="P:Telegrator.Result.Positive"> <member name="P:Telegrator.Result.Success">
<summary> <summary>
Is result positive Tell router to stop describing
</summary> </summary>
</member> </member>
<member name="P:Telegrator.Result.RouteNext"> <member name="P:Telegrator.Result.RouteNext">
<summary> <summary>
Should router search for next matching handler Tell router to continue describing
</summary> </summary>
</member> </member>
<member name="P:Telegrator.Result.NextType"> <member name="P:Telegrator.Result.NextType">
@@ -6449,6 +6457,14 @@
<param name="keySelector"></param> <param name="keySelector"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Telegrator.ColletionsExtensions.Squeeze``1(System.Collections.Generic.IEnumerable{``0})">
<summary>
Remove all <see langword="null"/> values and returns collection without nullable type.
</summary>
<typeparam name="T"></typeparam>
<param name="source"></param>
<returns></returns>
</member>
<member name="M:Telegrator.ColletionsExtensions.ForEach``1(System.Collections.Generic.IEnumerable{``0},System.Action{``0})"> <member name="M:Telegrator.ColletionsExtensions.ForEach``1(System.Collections.Generic.IEnumerable{``0},System.Action{``0})">
<summary> <summary>
Enumerates objects in a <paramref name="source"/> and executes an <paramref name="action"/> on each one Enumerates objects in a <paramref name="source"/> and executes an <paramref name="action"/> on each one
@@ -6558,7 +6574,7 @@
<param name="type"></param> <param name="type"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Telegrator.ReflectionExtensions.IsHandlerRealization(System.Type)"> <member name="M:Telegrator.ReflectionExtensions.IsHandlerImplementation(System.Type)">
<summary> <summary>
Checks if <paramref name="type"/> is an implementation of <see cref="T:Telegrator.Core.Handlers.UpdateHandlerBase"/> class or its descendants Checks if <paramref name="type"/> is an implementation of <see cref="T:Telegrator.Core.Handlers.UpdateHandlerBase"/> class or its descendants
</summary> </summary>
@@ -6796,13 +6812,8 @@
<param name="httpClient">Optional HTTP client for making requests.</param> <param name="httpClient">Optional HTTP client for making requests.</param>
<param name="cancellationToken">The cancellation token.</param> <param name="cancellationToken">The cancellation token.</param>
</member> </member>
<member name="M:Telegrator.TelegratorClient.StartReceiving(Telegram.Bot.Polling.ReceiverOptions,System.Threading.CancellationToken)"> <member name="M:Telegrator.TelegratorClient.StartReceivingAsync(Telegram.Bot.Polling.ReceiverOptions,System.Threading.CancellationToken)">
<summary> <inheritdoc/>
Starts receiving updates from Telegram.
Initializes the update router and begins polling for updates.
</summary>
<param name="receiverOptions">Optional receiver options for configuring update polling.</param>
<param name="cancellationToken">The cancellation token to stop receiving updates.</param>
</member> </member>
<member name="M:Telegrator.TelegratorClient.StartReceivingInternal(Telegram.Bot.Polling.ReceiverOptions,System.Threading.CancellationToken)"> <member name="M:Telegrator.TelegratorClient.StartReceivingInternal(Telegram.Bot.Polling.ReceiverOptions,System.Threading.CancellationToken)">
<summary> <summary>
@@ -6863,6 +6874,19 @@
Gets or sets the global cancellation token for all bot operations. Gets or sets the global cancellation token for all bot operations.
</summary> </summary>
</member> </member>
<member name="T:Telegrator.TelegratorBotExtensions">
<summary>
Provides usefull helper methods for TelegratorBot
</summary>
</member>
<member name="M:Telegrator.TelegratorBotExtensions.StartReceiving(Telegrator.ITelegratorBot,Telegram.Bot.Polling.ReceiverOptions,System.Threading.CancellationToken)">
<summary>
Initializes the update router and begins polling for updates synchronously (Blocking calling thread).
</summary>
<param name="bot"></param>
<param name="receiverOptions">Optional receiver options for configuring update polling.</param>
<param name="cancellationToken">The cancellation token to stop receiving updates.</param>
</member>
<member name="T:Telegrator.MessageExtensions"> <member name="T:Telegrator.MessageExtensions">
<summary> <summary>
Provides usefull helper methods for messages Provides usefull helper methods for messages
@@ -7113,6 +7137,14 @@
Provides convenient methods for creating implicit handlers. Provides convenient methods for creating implicit handlers.
</summary> </summary>
</member> </member>
<member name="M:Telegrator.HandlersCollectionExtensions.CollectHandlers(Telegrator.Core.IHandlersCollection)">
<summary>
Collects all handlers from current app domain.
Scans for handlers exported by analyzer into class `Telegrator.Analyzers.AnalyzerExport` in each assembly and registers them to the collection.
</summary>
<param name="handlers"></param>
<returns></returns>
</member>
<member name="M:Telegrator.HandlersCollectionExtensions.CollectHandlersDomainWide(Telegrator.Core.IHandlersCollection)"> <member name="M:Telegrator.HandlersCollectionExtensions.CollectHandlersDomainWide(Telegrator.Core.IHandlersCollection)">
<summary> <summary>
Collects all public handlers from the current app domain. Collects all public handlers from the current app domain.
@@ -13,6 +13,9 @@
<GenerateDocumentationFile>True</GenerateDocumentationFile> <GenerateDocumentationFile>True</GenerateDocumentationFile>
<EnableNETAnalyzers>True</EnableNETAnalyzers> <EnableNETAnalyzers>True</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild> <EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
<IncludeSymbols>True</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<SignAssembly>False</SignAssembly>
<Title>Telegrator.RedisStateStorage</Title> <Title>Telegrator.RedisStateStorage</Title>
<Version>1.16.6</Version> <Version>1.16.6</Version>
@@ -10,6 +10,8 @@ namespace Telegrator.Analyzers;
[Generator(LanguageNames.CSharp)] [Generator(LanguageNames.CSharp)]
public class DeveloperHelperAnalyzer : IIncrementalGenerator public class DeveloperHelperAnalyzer : IIncrementalGenerator
{ {
internal record class HandlerDeclarationModel(string ClassName, string NamespaceName, string? AttributeName, string? BaseClassName, Location Location);
private static readonly DiagnosticDescriptor MissingBaseClassWarning = new( private static readonly DiagnosticDescriptor MissingBaseClassWarning = new(
id: "TLG101", id: "TLG101",
title: "Missing handlers base class", title: "Missing handlers base class",
@@ -131,9 +133,8 @@ public class DeveloperHelperAnalyzer : IIncrementalGenerator
private static FieldDeclarationSyntax GenerateTypeField(HandlerDeclarationModel handler) private static FieldDeclarationSyntax GenerateTypeField(HandlerDeclarationModel handler)
{ {
string fullTypeName = handler.Namespace == "Global" string fullTypeName = handler.NamespaceName == "Global"
? handler.ClassName ? handler.ClassName : $"{handler.NamespaceName}.{handler.ClassName}";
: $"{handler.Namespace}.{handler.ClassName}";
TypeOfExpressionSyntax typeofExpression = SyntaxFactory.TypeOfExpression(SyntaxFactory.ParseTypeName(fullTypeName)); TypeOfExpressionSyntax typeofExpression = SyntaxFactory.TypeOfExpression(SyntaxFactory.ParseTypeName(fullTypeName));
VariableDeclaratorSyntax variableDeclarator = SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier($"{handler.ClassName}Type")) VariableDeclaratorSyntax variableDeclarator = SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier($"{handler.ClassName}Type"))
@@ -149,15 +150,6 @@ public class DeveloperHelperAnalyzer : IIncrementalGenerator
} }
} }
internal class HandlerDeclarationModel(string className, string namespaceName, string? attributeName, string? baseClassName, Location location)
{
public readonly string ClassName = className;
public readonly string Namespace = namespaceName;
public readonly string? AttributeName = attributeName;
public readonly string? BaseClassName = baseClassName;
public readonly Location Location = location;
}
internal static class DeveloperHelperAnalyzerExtensions internal static class DeveloperHelperAnalyzerExtensions
{ {
private static readonly string[] HandlersNames = private static readonly string[] HandlersNames =
@@ -8,8 +8,12 @@ using System.Text;
namespace Telegrator.Analyzers; namespace Telegrator.Analyzers;
[Generator(LanguageNames.CSharp)] [Generator(LanguageNames.CSharp)]
public class GeneratedKeyboardMarkupGenerator : IIncrementalGenerator public class KeyboardMarkupGenerator : IIncrementalGenerator
{ {
// Records
private record class GeneratedMarkupMethodModel(MethodDeclarationSyntax OriginalMethod, FieldDeclarationSyntax GeneratedField, MethodDeclarationSyntax GeneratedMethod);
private record class GeneratedMarkupPropertyModel(PropertyDeclarationSyntax OriginalProperty, PropertyDeclarationSyntax GeneratedProperty);
// Return types // Return types
private const string InlineReturnType = "InlineKeyboardMarkup"; private const string InlineReturnType = "InlineKeyboardMarkup";
private const string ReplyReturnType = "ReplyKeyboardMarkup"; private const string ReplyReturnType = "ReplyKeyboardMarkup";
@@ -459,30 +463,4 @@ public class GeneratedKeyboardMarkupGenerator : IIncrementalGenerator
SyntaxFactory.IdentifierName(className), SyntaxFactory.IdentifierName(className),
SyntaxFactory.IdentifierName(methodName)); SyntaxFactory.IdentifierName(methodName));
} }
private class GeneratedMarkupMethodModel
{
public MethodDeclarationSyntax OriginalMethod { get; }
public FieldDeclarationSyntax GeneratedField { get; }
public MethodDeclarationSyntax GeneratedMethod { get; }
public GeneratedMarkupMethodModel(MethodDeclarationSyntax originalMethod, FieldDeclarationSyntax generatedField, MethodDeclarationSyntax generatedMethod)
{
OriginalMethod = originalMethod;
GeneratedField = generatedField;
GeneratedMethod = generatedMethod;
}
}
private class GeneratedMarkupPropertyModel
{
public PropertyDeclarationSyntax OriginalProperty { get; }
public PropertyDeclarationSyntax GeneratedProperty { get; }
public GeneratedMarkupPropertyModel(PropertyDeclarationSyntax originalProperty, PropertyDeclarationSyntax generatedProperty)
{
OriginalProperty = originalProperty;
GeneratedProperty = generatedProperty;
}
}
} }
@@ -1,7 +1,7 @@
namespace Telegrator.Analyzers.RoslynExtensions; namespace Telegrator.Analyzers.RoslynExtensions;
public class TargteterNotFoundException() : Exception() { } #pragma warning disable RCS1194 // Implement exception constructors
public class TargteterNotFoundException() : Exception();
public class BaseClassTypeNotFoundException() : Exception() { } public class BaseClassTypeNotFoundException() : Exception();
public class AncestorNotFoundException() : Exception();
public class AncestorNotFoundException : Exception { } #pragma warning restore RCS1194 // Implement exception constructors
@@ -10,3 +10,5 @@ using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("Usage", "CA2254")] [assembly: SuppressMessage("Usage", "CA2254")]
[assembly: SuppressMessage("Maintainability", "CA1510")] [assembly: SuppressMessage("Maintainability", "CA1510")]
[assembly: SuppressMessage("Style", "IDE0270")] [assembly: SuppressMessage("Style", "IDE0270")]
[assembly: SuppressMessage("Roslynator", "RCS1037")]
[assembly: SuppressMessage("Roslynator", "RCS1224")]
@@ -1,159 +0,0 @@
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 Telegrator.Core;
namespace Telegrator.Hosting.Web;
/// <summary>
/// Represents a web hosted telegram bot
/// </summary>
public class TelegramBotWebHost : IHost, IApplicationBuilder, IEndpointRouteBuilder, IAsyncDisposable
{
private readonly WebApplication _innerApp;
private readonly IUpdateRouter _updateRouter;
private readonly ILogger<TelegramBotWebHost> _logger;
private bool _disposed;
/// <inheritdoc/>
public IServiceProvider Services => _innerApp.Services;
/// <inheritdoc/>
public IUpdateRouter UpdateRouter => _updateRouter;
/// <inheritdoc/>
public ICollection<EndpointDataSource> DataSources => ((IEndpointRouteBuilder)_innerApp).DataSources;
/// <summary>
/// Allows consumers to be notified of application lifetime events.
/// </summary>
public IHostApplicationLifetime Lifetime => _innerApp.Lifetime;
/// <summary>
/// This application's logger
/// </summary>
public ILogger<TelegramBotWebHost> Logger => _logger;
/// <inheritdoc/>
public IDictionary<string, object?> Properties => ((IApplicationBuilder)_innerApp).Properties;
// Private interface fields
IServiceProvider IEndpointRouteBuilder.ServiceProvider => Services;
IServiceProvider IApplicationBuilder.ApplicationServices { get => Services; set => throw new NotImplementedException(); }
IFeatureCollection IApplicationBuilder.ServerFeatures => ((IApplicationBuilder)_innerApp).ServerFeatures;
/// <summary>
/// Initializes a new instance of the <see cref="WebApplicationBuilder"/> class.
/// </summary>
/// <param name="webApplicationBuilder">The proxied instance of host builder.</param>
public TelegramBotWebHost(WebApplicationBuilder webApplicationBuilder)
{
// Building proxy application
_innerApp = webApplicationBuilder.Build();
// Reruesting services for this host
_updateRouter = Services.GetRequiredService<IUpdateRouter>();
_logger = Services.GetRequiredService<ILogger<TelegramBotWebHost>>();
}
/// <summary>
/// Creates new <see cref="TelegramBotHostBuilder"/> with default services and webhook update receiving scheme
/// </summary>
/// <returns></returns>
public static TelegramBotWebHostBuilder CreateBuilder(WebApplicationOptions? settings)
{
ArgumentNullException.ThrowIfNull(settings, nameof(settings));
WebApplicationBuilder innerApp = WebApplication.CreateBuilder(settings);
TelegramBotWebHostBuilder builder = new TelegramBotWebHostBuilder(innerApp);
builder.AddTelegratorWeb();
return builder;
}
/// <summary>
/// Creates new SLIM <see cref="TelegramBotHostBuilder"/> with default services and webhook update receiving scheme
/// </summary>
/// <returns></returns>
public static TelegramBotWebHostBuilder CreateSlimBuilder(WebApplicationOptions? settings)
{
ArgumentNullException.ThrowIfNull(settings, nameof(settings));
WebApplicationBuilder innerApp = WebApplication.CreateSlimBuilder(settings);
TelegramBotWebHostBuilder builder = new TelegramBotWebHostBuilder(innerApp);
builder.AddTelegratorWeb();
return builder;
}
/// <summary>
/// Creates new EMPTY <see cref="TelegramBotHostBuilder"/> WITHOUT any services or update receiving schemes
/// </summary>
/// <returns></returns>
public static TelegramBotWebHostBuilder CreateEmptyBuilder(WebApplicationOptions? settings)
{
ArgumentNullException.ThrowIfNull(settings, nameof(settings));
WebApplicationBuilder innerApp = WebApplication.CreateEmptyBuilder(settings);
TelegramBotWebHostBuilder builder = new TelegramBotWebHostBuilder(innerApp);
builder.AddTelegratorWeb();
return builder;
}
/// <inheritdoc/>
public async Task StartAsync(CancellationToken cancellationToken = default)
{
await _innerApp.StartAsync(cancellationToken);
}
/// <inheritdoc/>
public async Task StopAsync(CancellationToken cancellationToken = default)
{
await _innerApp.StopAsync(cancellationToken);
}
/// <inheritdoc/>
public IApplicationBuilder CreateApplicationBuilder()
=> ((IEndpointRouteBuilder)_innerApp).CreateApplicationBuilder();
/// <inheritdoc/>
public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
=> _innerApp.Use(middleware);
/// <inheritdoc/>
public IApplicationBuilder New()
=> ((IApplicationBuilder)_innerApp).New();
/// <inheritdoc/>
public RequestDelegate Build()
=> ((IApplicationBuilder)_innerApp).Build();
/// <summary>
/// Disposes the host.
/// </summary>
public async ValueTask DisposeAsync()
{
if (_disposed)
return;
await _innerApp.DisposeAsync();
GC.SuppressFinalize(this);
_disposed = true;
}
/// <summary>
/// Disposes the host.
/// </summary>
public void Dispose()
{
if (_disposed)
return;
ValueTask disposeTask = _innerApp.DisposeAsync();
disposeTask.AsTask().Wait();
GC.SuppressFinalize(this);
_disposed = true;
}
}
@@ -1,75 +0,0 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.Metrics;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Telegrator.Core;
#pragma warning disable IDE0001
namespace Telegrator.Hosting.Web;
/// <inheritdoc/>
public class TelegramBotWebHostBuilder : ITelegramBotHostBuilder
{
private readonly WebApplicationBuilder _innerBuilder;
internal IHandlersCollection _handlers = null!;
/// <inheritdoc/>
public IHandlersCollection Handlers => _handlers;
/// <inheritdoc/>
public IConfigurationManager Configuration => _innerBuilder.Configuration;
/// <inheritdoc/>
public ILoggingBuilder Logging => _innerBuilder.Logging;
/// <inheritdoc/>
public IServiceCollection Services => _innerBuilder.Services;
/// <inheritdoc/>
public IHostEnvironment Environment => _innerBuilder.Environment;
/// <inheritdoc/>
public IDictionary<object, object> Properties => ((IHostApplicationBuilder)_innerBuilder).Properties;
/// <inheritdoc/>
public IMetricsBuilder Metrics => _innerBuilder.Metrics;
/// <summary>
/// Initializes a new instance of the <see cref="TelegramBotWebHostBuilder"/> class.
/// </summary>
/// <param name="webApplicationBuilder"></param>
public TelegramBotWebHostBuilder(WebApplicationBuilder webApplicationBuilder)
{
_innerBuilder = webApplicationBuilder ?? throw new ArgumentNullException(nameof(webApplicationBuilder));
}
/// <summary>
/// Initializes a new instance of the <see cref="TelegramBotWebHostBuilder"/> class.
/// </summary>
/// <param name="webApplicationBuilder"></param>
/// <param name="handlers"></param>
public TelegramBotWebHostBuilder(WebApplicationBuilder webApplicationBuilder, IHandlersCollection handlers)
{
_innerBuilder = webApplicationBuilder ?? throw new ArgumentNullException(nameof(webApplicationBuilder));
_handlers = handlers ?? throw new ArgumentNullException(nameof(handlers));
}
/// <summary>
/// Builds the host.
/// </summary>
/// <returns></returns>
public TelegramBotWebHost Build()
{
TelegramBotWebHost host = new TelegramBotWebHost(_innerBuilder);
host.UseTelegratorWeb();
return host;
}
/// <inheritdoc/>
public void ConfigureContainer<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory, Action<TContainerBuilder>? configure = null) where TContainerBuilder : notnull
{
((IHostApplicationBuilder)_innerBuilder).ConfigureContainer(factory, configure);
}
}
@@ -8,12 +8,11 @@ using System.Text.Json;
using Telegram.Bot; using Telegram.Bot;
using Telegram.Bot.Types; using Telegram.Bot.Types;
using Telegrator.Core; using Telegrator.Core;
using Telegrator.Hosting.Web;
namespace Telegrator.Mediation; namespace Telegrator.Mediation;
/// <summary> /// <summary>
/// Service for receiving updates for Hosted telegram bots via Webhooks /// Service for receiving updates for Hosted telegram bots via Webhooks and queuing them to router
/// </summary> /// </summary>
public class HostedUpdateWebhooker : IHostedService public class HostedUpdateWebhooker : IHostedService
{ {
-85
View File
@@ -1,85 +0,0 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Telegrator.Hosting;
using Telegrator.Hosting.Web;
namespace Telegrator;
internal class Program
{
public static void TelegramBotWebHostBuilder_Example(string[] args)
{
TelegramBotWebHostBuilder builder = TelegramBotWebHost.CreateBuilder(new WebApplicationOptions()
{
Args = args,
ApplicationName = "TelegramBotWebHost example",
});
builder.Handlers
.CollectHandlersAssemblyWide();
builder.Build()
.AddLoggingAdapter()
.SetBotCommands()
.Run();
}
public static void WebApplicationBuilder_Example(string[] args)
{
WebApplicationBuilder builder = WebApplication.CreateBuilder(new WebApplicationOptions()
{
Args = args,
ApplicationName = "WebApplication example",
});
builder.AddTelegratorWeb(action: builder => builder.Handlers
.CollectHandlersAssemblyWide());
builder.Build()
.UseTelegratorWeb(dontMap: true)
.RemapWebhook("https://awesome-butt-sex.cloudpub.ru/")
.AddLoggingAdapter()
.SetBotCommands()
.Run();
}
public static void TelegramBotHostBuilder_Example(string[] args)
{
ConfigurationManager configuration = new ConfigurationManager();
configuration.AddJsonFile("appsettings.json");
TelegramBotHostBuilder builder = TelegramBotHost.CreateBuilder(new HostApplicationBuilderSettings()
{
Args = args,
ApplicationName = "TelegramBotHost example",
Configuration = configuration
});
builder.Handlers
.CollectHandlersAssemblyWide();
builder.Build()
.AddLoggingAdapter()
.SetBotCommands()
.Run();
}
public static void HostApplicationBuilder_Example(string[] args)
{
HostApplicationBuilder builder = Host.CreateApplicationBuilder(new HostApplicationBuilderSettings()
{
Args = args,
ApplicationName = "Host example",
});
builder.AddTelegrator(action: builder => builder.Handlers
.CollectHandlersAssemblyWide());
builder.Build()
.UseTelegrator()
.AddLoggingAdapter()
.SetBotCommands()
.Run();
}
}
@@ -13,9 +13,12 @@
<GenerateDocumentationFile>True</GenerateDocumentationFile> <GenerateDocumentationFile>True</GenerateDocumentationFile>
<EnableNETAnalyzers>True</EnableNETAnalyzers> <EnableNETAnalyzers>True</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild> <EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
<IncludeSymbols>True</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<SignAssembly>False</SignAssembly>
<Title>Telegrator.Hosting.Web</Title> <Title>Telegrator.Hosting.Web</Title>
<Version>1.16.9</Version> <Version>1.17.1</Version>
<Authors>Rikitav Tim4ik</Authors> <Authors>Rikitav Tim4ik</Authors>
<Company>Rikitav Tim4ik</Company> <Company>Rikitav Tim4ik</Company>
<RepositoryUrl>https://github.com/Rikitav/Telegrator</RepositoryUrl> <RepositoryUrl>https://github.com/Rikitav/Telegrator</RepositoryUrl>
@@ -40,4 +43,5 @@
<None Include="..\..\LICENSE" Pack="True" PackagePath="\" /> <None Include="..\..\LICENSE" Pack="True" PackagePath="\" />
<None Include="..\..\resources\telegrator_nuget.png" Pack="True" PackagePath="\" /> <None Include="..\..\resources\telegrator_nuget.png" Pack="True" PackagePath="\" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+61 -42
View File
@@ -1,5 +1,4 @@
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
@@ -10,43 +9,32 @@ using System.Diagnostics.CodeAnalysis;
using Telegram.Bot; using Telegram.Bot;
using Telegrator.Core; using Telegrator.Core;
using Telegrator.Hosting; using Telegrator.Hosting;
using Telegrator.Hosting.Web;
using Telegrator.Mediation; using Telegrator.Mediation;
using Telegrator.Providers; using Telegrator.Providers;
namespace Telegrator namespace Telegrator;
{
/// <summary>
/// Contains extensions for <see cref="IServiceCollection"/>
/// Provides method to configure Telegram Bot WebHost
/// </summary>
public static class ServicesCollectionExtensions
{
/// <summary>
/// The key used to store the <see cref="IHandlersCollection"/> in the builder properties.
/// </summary>
public const string HandlersCollectionPropertyKey = nameof(IHandlersCollection);
/// <summary>
/// Provides extension methods for <see cref="IHostApplicationBuilder"/> to configure Telegrator.
/// </summary>
public static class WebHostBuilderExtensions
{
/// <summary> /// <summary>
/// Replaces TelegramBotWebHostBuilder. Configures DI, options, and handlers. /// Replaces TelegramBotWebHostBuilder. Configures DI, options, and handlers.
/// </summary> /// </summary>
public static ITelegramBotHostBuilder AddTelegratorWeb(this ITelegramBotHostBuilder builder, TelegratorOptions? options = null, IHandlersCollection? handlers = null, Action<ITelegramBotHostBuilder>? action = null) public static IHostApplicationBuilder AddTelegratorWeb(this IHostApplicationBuilder builder, TelegratorOptions? options = null, IHandlersCollection? handlers = null)
{ {
AddTelegratorWebInternal(builder.Services, builder.Configuration, builder.Properties, ref handlers, options); AddTelegratorWebInternal(builder.Services, builder.Configuration, builder.Properties, ref handlers, options);
if (builder is TelegramBotWebHostBuilder telegramBotHostBuilder)
telegramBotHostBuilder._handlers = handlers;
action?.Invoke(builder);
return builder; return builder;
} }
/// <summary> /// <summary>
/// Replaces TelegramBotWebHostBuilder. Configures DI, options, and handlers. /// Replaces TelegramBotWebHostBuilder. Configures DI, options, and handlers.
/// </summary> /// </summary>
public static IHostApplicationBuilder AddTelegratorWeb(this WebApplicationBuilder builder, TelegratorOptions? options = null, IHandlersCollection? handlers = null, Action<ITelegramBotHostBuilder>? action = null) public static IHostApplicationBuilder AddTelegratorWeb(this IHostApplicationBuilder builder, TelegratorOptions? options = null, IHandlersCollection? handlers = null, Action<ITelegramBotHostBuilder>? action = null)
{ {
AddTelegratorWebInternal(builder.Services, builder.Configuration, ((IHostApplicationBuilder)builder).Properties, ref handlers, options); AddTelegratorWebInternal(builder.Services, builder.Configuration, builder.Properties, ref handlers, options);
action?.Invoke(new TelegramBotWebHostBuilder(builder, handlers)); action?.Invoke(new TelegramBotHostBuilder(builder, handlers));
return builder; return builder;
} }
@@ -55,11 +43,14 @@ namespace Telegrator
/// </summary> /// </summary>
internal static void AddTelegratorWebInternal(IServiceCollection services, IConfiguration configuration, IDictionary<object, object> properties, [NotNull] ref IHandlersCollection? handlers, TelegratorOptions? options = null) internal static void AddTelegratorWebInternal(IServiceCollection services, IConfiguration configuration, IDictionary<object, object> properties, [NotNull] ref IHandlersCollection? handlers, TelegratorOptions? options = null)
{ {
if (options == null) if (services.Any(srvc => srvc.ServiceType == typeof(HostedUpdateReceiver)))
throw new InvalidOperationException("`HostedUpdateReceiver` found in services. WebHost extension is not compatible with long-polling receiving. Please, remove `AddTelegrator` invocation from your WebApp configuration.");
if (options is null)
{ {
options = configuration.GetSection(nameof(TelegratorOptions)).Get<TelegratorOptions>(); options = configuration.GetSection(nameof(TelegratorOptions)).Get<TelegratorOptions>();
if (options == null) if (options is null)
throw new MissingMemberException("Auto configuration disabled, yet no options of type 'TelegratorOptions' wasn't registered. This configuration is runtime required!"); throw new MissingMemberException("Auto configuration disabled, yet no options of type 'TelegratorOptions' was registered. This configuration is runtime required!");
} }
CancellationTokenSource globallCancell = new CancellationTokenSource(); CancellationTokenSource globallCancell = new CancellationTokenSource();
@@ -67,25 +58,22 @@ namespace Telegrator
services.AddSingleton(Options.Create(options)); services.AddSingleton(Options.Create(options));
services.AddKeyedSingleton("cancell", globallCancell); services.AddKeyedSingleton("cancell", globallCancell);
if (handlers != null) if (handlers is not null && handlers is IHandlersManager manager)
{
if (handlers is IHandlersManager manager)
{ {
ServiceDescriptor descriptor = new ServiceDescriptor(typeof(IHandlersProvider), manager); ServiceDescriptor descriptor = new ServiceDescriptor(typeof(IHandlersProvider), manager);
services.Replace(descriptor); services.Replace(descriptor);
services.AddSingleton(manager); services.AddSingleton(manager);
} }
}
handlers ??= new HostHandlersCollection(services, options); handlers ??= new HostHandlersCollection(services, options);
services.AddSingleton(handlers); services.AddSingleton(handlers);
properties.Add(HandlersCollectionPropertyKey, handlers); properties.Add(HostBuilderExtensions.HandlersCollectionPropertyKey, handlers);
if (!services.Any(srvc => srvc.ImplementationType == typeof(IOptions<WebhookerOptions>))) if (!services.Any(srvc => srvc.ServiceType == typeof(IOptions<WebhookerOptions>)))
{ {
WebhookerOptions? webhookerOptions = configuration.GetSection(nameof(WebhookerOptions)).Get<WebhookerOptions>(); WebhookerOptions? webhookerOptions = configuration.GetSection(nameof(WebhookerOptions)).Get<WebhookerOptions>();
if (webhookerOptions == null) if (webhookerOptions == null)
throw new MissingMemberException("Auto configuration disabled, yet no options of type 'WebhookerOptions' wasn't registered. This configuration is runtime required!"); throw new MissingMemberException("Auto configuration disabled, yet no options of type 'WebhookerOptions' was registered. This configuration is runtime required!");
services.AddSingleton(Options.Create(webhookerOptions)); services.AddSingleton(Options.Create(webhookerOptions));
} }
@@ -102,6 +90,26 @@ namespace Telegrator
services.AddTelegramBotHostDefaults(); services.AddTelegramBotHostDefaults();
services.AddTelegramWebhook(); services.AddTelegramWebhook();
} }
}
/// <summary>
/// Contains extensions for <see cref="IServiceCollection"/>
/// Provides method to configure Telegram Bot WebHost
/// </summary>
public static class WebServicesCollectionExtensions
{
/// <summary>
/// Adds WebhookerOptions to services
/// </summary>
/// <param name="services"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IServiceCollection ConfigureWebhooker(this IServiceCollection services, WebhookerOptions options)
{
services.RemoveAll<IOptions<WebhookerOptions>>();
services.AddSingleton(Options.Create(options));
return services;
}
/// <summary> /// <summary>
/// Searchs for <see cref="HostedUpdateWebhooker"/> hosted service inside hosts services /// Searchs for <see cref="HostedUpdateWebhooker"/> hosted service inside hosts services
@@ -114,32 +122,41 @@ namespace Telegrator
webhooker = services.GetServices<IHostedService>().FirstOrDefault(s => s is HostedUpdateWebhooker) as HostedUpdateWebhooker; webhooker = services.GetServices<IHostedService>().FirstOrDefault(s => s is HostedUpdateWebhooker) as HostedUpdateWebhooker;
return webhooker != null; return webhooker != null;
} }
}
/// <summary>
/// Provides useful methods to adjust Telegram bot Host
/// </summary>
public static class WebTelegramBotHostExtensions
{
/// <summary> /// <summary>
/// Replaces the initialization logic from TelegramBotWebHost constructor. /// Replaces the initialization logic from TelegramBotWebHost constructor.
/// Initializes the bot and logs handlers on application startup. /// Initializes the bot and logs handlers on application startup.
/// </summary> /// </summary>
public static T UseTelegratorWeb<T>(this T app, bool dontMap = false) where T : IEndpointRouteBuilder, IHost public static T UseTelegratorWeb<T>(this T botHost, bool dontMap = false) where T : IEndpointRouteBuilder, IHost
{ {
if (!app.ServiceProvider.TryFindWebhooker(out HostedUpdateWebhooker? webhooker)) if (!botHost.ServiceProvider.TryFindWebhooker(out HostedUpdateWebhooker? webhooker))
throw new InvalidOperationException("No service for type 'Telegrator.Mediation.HostedUpdateWebhooker' has been registered."); throw new InvalidOperationException("No service for type 'Telegrator.Mediation.HostedUpdateWebhooker' has been registered.");
ITelegramBotInfo info = app.ServiceProvider.GetRequiredService<ITelegramBotInfo>(); ITelegramBotInfo info = botHost.ServiceProvider.GetRequiredService<ITelegramBotInfo>();
IHandlersCollection handlers = app.ServiceProvider.GetRequiredService<IHandlersCollection>(); IHandlersCollection handlers = botHost.ServiceProvider.GetRequiredService<IHandlersCollection>();
ILoggerFactory loggerFactory = app.ServiceProvider.GetRequiredService<ILoggerFactory>(); ILoggerFactory loggerFactory = botHost.ServiceProvider.GetRequiredService<ILoggerFactory>();
ILogger logger = loggerFactory.CreateLogger("Telegrator.Hosting.Web.TelegratorHost"); ILogger logger = loggerFactory.CreateLogger("Telegrator.Hosting.Web.TelegratorHost");
if (logger.IsEnabled(LogLevel.Information)) if (logger.IsEnabled(LogLevel.Information))
{ {
logger.LogInformation("Telegrator Bot ASP.NET WebHost started"); logger.LogInformation("Telegrator Bot Host started (ASP.NET WebHost)");
logger.LogInformation("Receiving mode : WEB-HOOKING");
logger.LogInformation("Telegram Bot : {firstname}, @{usrname}, id:{id},", info.User.FirstName ?? "[NULL]", info.User.Username ?? "[NULL]", info.User.Id); logger.LogInformation("Telegram Bot : {firstname}, @{usrname}, id:{id},", info.User.FirstName ?? "[NULL]", info.User.Username ?? "[NULL]", info.User.Id);
logger.LogHandlers(handlers); logger.LogHandlers(handlers);
} }
if (!dontMap) if (!dontMap)
webhooker.MapWebhook(app); webhooker.MapWebhook(botHost);
return app; botHost.AddLoggingAdapter();
botHost.SetBotCommands();
return botHost;
} }
/// <summary> /// <summary>
@@ -165,6 +182,9 @@ namespace Telegrator
/// <returns></returns> /// <returns></returns>
public static IServiceCollection AddTelegramWebhook(this IServiceCollection services) public static IServiceCollection AddTelegramWebhook(this IServiceCollection services)
{ {
services.RemoveAll<IOptions<HostedUpdateWebhooker>>();
services.RemoveAll<ITelegramBotClient>();
services.AddHttpClient<ITelegramBotClient>("tgwebhook").RemoveAllLoggers().AddTypedClient(TypedTelegramBotClientFactory); services.AddHttpClient<ITelegramBotClient>("tgwebhook").RemoveAllLoggers().AddTypedClient(TypedTelegramBotClientFactory);
services.AddHostedService<HostedUpdateWebhooker>(); services.AddHostedService<HostedUpdateWebhooker>();
return services; return services;
@@ -172,5 +192,4 @@ namespace Telegrator
private static ITelegramBotClient TypedTelegramBotClientFactory(HttpClient httpClient, IServiceProvider provider) private static ITelegramBotClient TypedTelegramBotClientFactory(HttpClient httpClient, IServiceProvider provider)
=> new TelegramBotClient(provider.GetRequiredService<IOptions<TelegramBotClientOptions>>().Value, httpClient); => new TelegramBotClient(provider.GetRequiredService<IOptions<TelegramBotClientOptions>>().Value, httpClient);
}
} }
@@ -1,6 +1,6 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
namespace Telegrator.Hosting.Web; namespace Telegrator;
/// <summary> /// <summary>
/// Configuration options for Telegram bot behavior and execution settings. /// Configuration options for Telegram bot behavior and execution settings.
@@ -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("Roslynator", "RCS1037")]
[assembly: SuppressMessage("Style", "IDE0090")]
[assembly: SuppressMessage("Style", "IDE0270")]
@@ -0,0 +1,39 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Telegram.Bot;
using Telegram.Bot.Polling;
using Telegrator.Core;
namespace Telegrator.Mediation;
/// <summary>
/// Service for receiving updates for Hosted wide telegram bots and queuing them to router
/// </summary>
/// <param name="logger"></param>
/// <param name="botClient"></param>
/// <param name="updateRouter"></param>
/// <param name="options"></param>
public class HostedWideBotUpdateReceiver(ILogger<HostedWideBotUpdateReceiver> logger, ITelegramBotClient botClient, IUpdateRouter updateRouter, IOptions<WideBotOptions>? options) : BackgroundService
{
/// <inheritdoc/>
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
if (botClient is not WTelegramBotClient wideBotClient)
throw new Exception("Registered ITelegramBotClient was not a wide client (WTelegramBotClient)! Please, use `AddWideTelegrator` instead.");
if (options?.Value.DropPendingUpdates is true)
await wideBotClient.DropPendingUpdates();
logger.LogInformation("Starting receiving updates via MTProto");
// UIP (understanding in progress)
//_receiverOptions.AllowedUpdates = updateRouter.HandlersProvider.AllowedTypes.ToArray();
botClient.DeleteWebhook(options?.Value.DropPendingUpdates ?? false, cancellationToken: stoppingToken)
.ConfigureAwait(false).GetAwaiter().GetResult();
WideUpdateReceiver updateReceiver = new WideUpdateReceiver(wideBotClient);
await updateReceiver.ReceiveAsync(updateRouter, stoppingToken).ConfigureAwait(false);
}
}
@@ -0,0 +1,57 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Telegram.Bot;
using Telegram.Bot.Polling;
using Telegrator.Core;
using WUpdate = WTelegram.Types.Update;
namespace Telegrator.Mediation;
/// <summary>
/// Reactive implementation of <see cref="IUpdateReceiver"/> for polling updates from Telegram.
/// Provides custom update receiving logic with error handling and configuration options.
/// </summary>
/// <param name="client">The Telegram bot client for making API requests.</param>
// <param name="options">Optional receiver options for configuring update polling behavior.</param>
public class WideUpdateReceiver(WTelegramBotClient client) : IUpdateReceiver
{
private readonly WTelegramBotClient _client = client;
private IUpdateHandler? _updateHandler = null;
private CancellationToken _cancellation = default;
/// <inheritdoc/>
public async Task ReceiveAsync(IUpdateHandler updateHandler, CancellationToken cancellationToken = default)
{
_updateHandler = updateHandler;
_cancellation = cancellationToken;
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
await using CancellationTokenRegistration registration = cancellationToken.Register(() => tcs.TrySetResult(null!));
try
{
_client.OnUpdate += OnUpdate;
await tcs.Task.ConfigureAwait(false);
}
finally
{
_client.OnUpdate -= OnUpdate;
}
}
private async Task OnUpdate(WUpdate update)
{
if (_updateHandler == null)
throw new Exception("Router not initialized (got null)");
try
{
await _updateHandler.HandleUpdateAsync(_client, update, _cancellation).ConfigureAwait(false);
}
catch (Exception ex)
{
await _updateHandler.HandleErrorAsync(_client, ex, HandleErrorSource.HandleUpdateError, _cancellation).ConfigureAwait(false);
}
}
}
+1
View File
@@ -0,0 +1 @@
@@ -0,0 +1,46 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<RootNamespace>Telegrator</RootNamespace>
<BaseOutputPath>..\..\bin</BaseOutputPath>
<DocumentationFile>..\..\docs\$(AssemblyName).xml</DocumentationFile>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<EnableNETAnalyzers>True</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
<IncludeSymbols>True</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<SignAssembly>False</SignAssembly>
<Title>Telegrator.Hosting.WideBot</Title>
<Version>1.17.1</Version>
<Authors>Rikitav Tim4ik</Authors>
<Company>Rikitav Tim4ik</Company>
<RepositoryUrl>https://github.com/Rikitav/Telegrator</RepositoryUrl>
<PackageTags>telegram;bot;mediator;attributes;aspect;hosting;host;framework;easy;simple;handlers;wtelegrambot;userbot</PackageTags>
<PackageIcon>telegrator_nuget.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="WTelegramBot" Version="9.5.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Telegrator.Hosting\Telegrator.Hosting.csproj" />
</ItemGroup>
<ItemGroup>
<None Include=".\README.md" Pack="True" PackagePath="\" />
<None Include="..\..\LICENSE" Pack="True" PackagePath="\" />
<None Include="..\..\resources\telegrator_nuget.png" Pack="True" PackagePath="\" />
</ItemGroup>
</Project>
@@ -0,0 +1,107 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Net.Http;
using System.Threading;
using Telegram.Bot;
using Telegram.Bot.Polling;
using Telegrator.Core;
using Telegrator.Logging;
using Telegrator.Mediation;
using Telegrator.Providers;
using Telegrator.States;
namespace Telegrator;
/// <summary>
/// Client class for the Telegrator library with Wider functionality, provided by WTelegramBotClient.
/// Extends TelegramBotClient with reactive capabilities for handling updates.
/// </summary>
public class TelegratorWClient : WTelegramBotClient, ITelegratorBot, ICollectingProvider
{
private IUpdateRouter? _updateRouter = null;
/// <inheritdoc/>
public TelegratorOptions Options { get; }
/// <inheritdoc/>
public IHandlersCollection Handlers { get; }
/// <inheritdoc/>
public ITelegramBotInfo BotInfo { get; }
/// <inheritdoc/>
public IUpdateRouter UpdateRouter => _updateRouter ?? throw new InvalidOperationException("Router's not created yet. Invoke `StartReceiving` to initialize this property.");
/// <summary>
/// Initializes new instance of <see cref="TelegratorWClient"/>
/// </summary>
/// <param name="wOptions"></param>
/// <param name="telegratorOptions"></param>
/// <param name="httpClient"></param>
/// <param name="cancellationToken"></param>
public TelegratorWClient(WTelegramBotClientOptions wOptions, TelegratorOptions? telegratorOptions = null, HttpClient? httpClient = null, CancellationToken cancellationToken = default)
: base(wOptions, httpClient, cancellationToken)
{
Options = telegratorOptions ?? new TelegratorOptions();
Handlers = new HandlersCollection(default);
BotInfo = new TelegramBotInfo(GetMe(cancellationToken).Result);
}
/// <inheritdoc/>
public void StartReceiving(ReceiverOptions? _, CancellationToken cancellationToken = default)
{
if (Options.GlobalCancellationToken == CancellationToken.None)
Options.GlobalCancellationToken = cancellationToken;
HandlersProvider handlerProvider = new HandlersProvider(Handlers, Options);
AwaitingProvider awaitingProvider = new AwaitingProvider(Options);
DefaultStateStorage stateStorage = new DefaultStateStorage();
_updateRouter = new UpdateRouter(handlerProvider, awaitingProvider, stateStorage, Options, BotInfo);
TelegratorLogging.LogInformation($"TelegratorW bot starting up - BotId: {BotInfo.User.Id}, Username: {BotInfo.User.Username}");
StartReceivingInternal(Options.GlobalCancellationToken)
.ConfigureAwait(false).GetAwaiter().GetResult();
}
/// <inheritdoc/>
public async Task StartReceivingAsync(ReceiverOptions? receiverOptions = null,CancellationToken cancellationToken = default)
{
if (Options.GlobalCancellationToken == CancellationToken.None)
Options.GlobalCancellationToken = cancellationToken;
HandlersProvider handlerProvider = new HandlersProvider(Handlers, Options);
AwaitingProvider awaitingProvider = new AwaitingProvider(Options);
DefaultStateStorage stateStorage = new DefaultStateStorage();
_updateRouter = new UpdateRouter(handlerProvider, awaitingProvider, stateStorage, Options, BotInfo);
TelegratorLogging.LogInformation($"TelegratorW bot starting up - BotId: {BotInfo.User.Id}, Username: {BotInfo.User.Username}");
await StartReceivingInternal(Options.GlobalCancellationToken);
}
private async Task StartReceivingInternal(CancellationToken cancellationToken)
{
try
{
try
{
await new HostedWideBotUpdateReceiver(NullLoggerFactory.Instance.CreateLogger<HostedWideBotUpdateReceiver>(), this, UpdateRouter, null)
.StartAsync(cancellationToken)
.ConfigureAwait(false);
}
catch (Exception exception)
{
await UpdateRouter
.HandleErrorAsync(this, exception, HandleErrorSource.FatalError, cancellationToken)
.ConfigureAwait(false);
}
}
catch (OperationCanceledException)
{
// Cancelled
TelegratorLogging.LogInformation("Telegrator bot stopped (cancelled)");
}
}
}
@@ -0,0 +1,298 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Diagnostics.CodeAnalysis;
using Telegram.Bot;
using Telegram.Bot.Types;
using Telegrator.Core;
using Telegrator.Core.Handlers;
using Telegrator.Hosting;
using Telegrator.Mediation;
using Telegrator.Providers;
using WUpdate = WTelegram.Types.Update;
using TLUpdate = TL.Update;
using System.Data.Common;
namespace Telegrator;
/// <summary>
/// Provides extensions memebrs for <see cref="UpdateHandlerBase"/> for easy access to Wider bot functions and update
/// </summary>
public static class HandlersExtensions
{
extension<TUpdate>(AbstractUpdateHandler<TUpdate> handler) where TUpdate : class
{
/// <summary>
/// Casts Update to <see cref="WTelegramBotClient"/>
/// </summary>
public WTelegramBotClient WClient
{
get
{
object? client = handler.GetType().GetField("Client")?.GetValue(handler);
if (client is not WTelegramBotClient wideClient)
throw new InvalidCastException("Client is not assignable to `WTelegram.Bot.WTelegramBotClient`");
return wideClient;
}
}
/// <summary>
/// Casts Update to <see cref="WUpdate"/>
/// </summary>
public WUpdate WideUpdate
{
get
{
object? update = handler.GetType().GetField("HandlingUpdate")?.GetValue(handler);
if (update is not WUpdate wUpdate)
throw new InvalidCastException("Update is not assignable to `WTelegram.Types.Update`");
return wUpdate;
}
}
/// <summary>
/// Casts Update to <see cref="TLUpdate"/>
/// </summary>
public TLUpdate? TLUpdate
{
get => handler.WideUpdate.TLUpdate;
}
}
/// <summary>
/// Casts Update to <see cref="WTelegramBotClient"/>
/// </summary>
public static WTelegramBotClient AsWClient(this ITelegramBotClient client)
{
return client as WTelegramBotClient
?? throw new InvalidCastException("Client is not assignable to `WTelegram.Bot.WTelegramBotClient`");
}
/// <summary>
/// Casts Update to <see cref="WUpdate"/>
/// </summary>
public static WUpdate AsWUpdate(this Update update)
{
return update as WUpdate
?? throw new InvalidCastException("Update is not assignable to `WTelegram.Types.Update`");
}
}
/// <summary>
/// Provides extension methods for <see cref="IHostApplicationBuilder"/> to configure Telegrator.
/// </summary>
public static class WideHostBuilderExtensions
{
/// <summary>
/// Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
/// </summary>
public static IHostApplicationBuilder AddWideTelegrator(this IHostApplicationBuilder builder, Func<IServiceProvider, DbConnection> dbConnectionFactory, Action<ITelegramBotHostBuilder>? action = null, TelegratorOptions? options = null, IHandlersCollection? handlers = null)
{
AddWideTelegratorInternal(builder.Services, builder.Configuration, builder.Properties, dbConnectionFactory, ref handlers, options);
action?.Invoke(new TelegramBotHostBuilder(builder, handlers));
return builder;
}
/// <summary>
/// Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
/// </summary>
public static IHostApplicationBuilder AddWideTelegrator(this IHostApplicationBuilder builder, Func<IServiceProvider, DbConnection> dbConnectionFactory, TelegratorOptions? options = null, IHandlersCollection? handlers = null)
{
AddWideTelegratorInternal(builder.Services, builder.Configuration, builder.Properties, dbConnectionFactory, ref handlers, options);
return builder;
}
/// <summary>
/// Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
/// </summary>
internal static void AddWideTelegratorInternal(IServiceCollection services, IConfiguration configuration, IDictionary<object, object> properties, Func<IServiceProvider, DbConnection> dbConnectionFactory, [NotNull] ref IHandlersCollection? handlers, TelegratorOptions? options = null)
{
if (services.Any(srvc => srvc.ServiceType == typeof(HostedUpdateReceiver)))
throw new InvalidOperationException("`HostedUpdateReceiver` found in services. WideHost extension is not compatible with default long-polling receiver. Please, remove `AddTelegrator` invocation from your Host configuration.");
if (services.Any(srvc => srvc.ServiceType.Name == "HostedUpdateWebhooker"))
throw new InvalidOperationException("`HostedUpdateWebhooker` found in services. WideHost extension is not compatible with webhooking yet. Please, remove `AddWebTelegrator` invocation from your Host configuration.");
if (options == null)
{
options = configuration.GetSection(nameof(TelegratorOptions)).Get<TelegratorOptions>();
if (options == null)
throw new MissingMemberException("Auto configuration disabled, yet no options of type 'TelegratorOptions' was registered. This configuration is runtime required!");
}
CancellationTokenSource globallCancell = new CancellationTokenSource();
options.GlobalCancellationToken = globallCancell.Token;
services.AddSingleton(Options.Create(options));
services.AddKeyedSingleton("cancell", globallCancell);
if (handlers != null)
{
if (handlers is IHandlersManager manager)
{
ServiceDescriptor descriptor = new ServiceDescriptor(typeof(IHandlersProvider), manager);
services.Replace(descriptor);
services.AddSingleton(manager);
}
}
handlers ??= new HostHandlersCollection(services, options);
services.AddSingleton(handlers);
properties.Add(HostBuilderExtensions.HandlersCollectionPropertyKey, handlers);
if (!services.Any(srvc => srvc.ServiceType == typeof(IOptions<WTelegramBotClientOptions>)))
{
WideBotOptions? wideBotOptions = configuration.GetSection(nameof(WideBotOptions)).Get<WideBotOptions>();
if (wideBotOptions == null)
throw new MissingMemberException("Auto configuration disabled, yet no options of type 'WideBotOptions' was registered. This configuration is runtime required!");
services.AddSingleton(provider =>
{
IHostApplicationLifetime lifetime = provider.GetRequiredService<IHostApplicationLifetime>();
DbConnection dbConnection = dbConnectionFactory.Invoke(provider);
lifetime.ApplicationStopping.Register(() => dbConnection.Dispose());
WTelegramBotClientOptions wideOptions = new WTelegramBotClientOptions(
token: options.Token,
apiId: wideBotOptions.ApiId,
apiHash: wideBotOptions.ApiHash,
dbConnection: dbConnection,
sqlCommands: wideBotOptions.SqlCommands,
useTestEnvironment: options.UseTestEnvironment,
mtproxy: wideBotOptions.MTProxy)
{
RetryCount = options.RetryCount,
RetryThreshold = options.RetryThreshold
};
return Options.Create(wideOptions);
});
}
services.AddTelegramBotHostDefaults();
services.AddMTProtoUpdateReceiver();
}
}
/// <summary>
/// Contains extensions for <see cref="IServiceCollection"/>
/// Provides method to configure Telegram Bot WebHost
/// </summary>
public static class WideBotServiceCollectionExtensions
{
/// <summary>
/// Adds WTelegramBotClientOptions to services
/// </summary>
/// <param name="services"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IServiceCollection ConfigureWideTelegram(this IServiceCollection services, WTelegramBotClientOptions options)
{
services.RemoveAll<IOptions<WTelegramBotClientOptions>>();
services.AddSingleton(Options.Create(options));
return services;
}
/// <summary>
/// Adds WTelegramBotClientOptions to services
/// </summary>
/// <param name="services"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IServiceCollection ConfigureWideBot(this IServiceCollection services, WideBotOptions options)
{
services.RemoveAll<IOptions<WideBotOptions>>();
services.AddSingleton(Options.Create(options));
return services;
}
/// <summary>
/// Adds WTelegramBotClient
/// </summary>
/// <param name="services"></param>
/// <param name="useHttp"></param>
/// <returns></returns>
public static IServiceCollection AddMTProtoUpdateReceiver(this IServiceCollection services, bool useHttp = false)
{
services.RemoveAll<ITelegramBotClient>();
services.RemoveAll<HostedWideBotUpdateReceiver>();
if (useHttp)
{
services.AddHttpClient<WTelegramBotClient>("tgmtproto").RemoveAllLoggers().AddTypedClient(TypedTelegramBotClientFactory);
}
else
{
services.AddSingleton(TypedTelegramBotClientFactory);
}
services.AddSingleton<ITelegramBotClient>(sp => sp.GetRequiredService<WTelegramBotClient>());
services.AddHostedService<HostedWideBotUpdateReceiver>();
return services;
}
#pragma warning disable CA2254
private static WTelegramBotClient TypedTelegramBotClientFactory(HttpClient httpClient, IServiceProvider provider)
{
ILogger<WTelegramBotClient> logger = provider.GetRequiredService<ILogger<WTelegramBotClient>>();
WTelegramBotClient client = new WTelegramBotClient(provider.GetRequiredService<IOptions<WTelegramBotClientOptions>>().Value, httpClient);
WTelegram.Helpers.Log = (lvl, str) => logger.Log((LogLevel)lvl, str);
return client;
}
private static WTelegramBotClient TypedTelegramBotClientFactory(IServiceProvider provider)
{
ILogger<WTelegramBotClient> logger = provider.GetRequiredService<ILogger<WTelegramBotClient>>();
WTelegramBotClient client = new WTelegramBotClient(provider.GetRequiredService<IOptions<WTelegramBotClientOptions>>().Value);
WTelegram.Helpers.Log = (lvl, str) => logger.Log((LogLevel)lvl, str);
return client;
}
#pragma warning restore CA2254
}
/// <summary>
/// Provides useful methods to adjust Telegram bot Host
/// </summary>
public static class WideTelegramBotHostExtensions
{
/// <summary>
/// Replaces the initialization logic from TelegramBotWebHost constructor.
/// Initializes the bot and logs handlers on application startup.
/// </summary>
public static IHost UseWideTelegrator(this IHost botHost)
{
if (!botHost.Services.TryFindWTelegramBotClient())
throw new InvalidOperationException("No service for type 'Telegram.Bot.WTelegramBotClient' has been registered. Invoke `AddWideTelegrator`");
ITelegramBotInfo info = botHost.Services.GetRequiredService<ITelegramBotInfo>();
IHandlersCollection handlers = botHost.Services.GetRequiredService<IHandlersCollection>();
ILoggerFactory loggerFactory = botHost.Services.GetRequiredService<ILoggerFactory>();
ILogger logger = loggerFactory.CreateLogger("Telegrator.Hosting.Web.TelegratorHost");
if (logger.IsEnabled(LogLevel.Information))
{
logger.LogInformation("Telegrator WIDE Bot Host started (Generic Host)");
logger.LogInformation("Receiving mode : MTProto");
logger.LogInformation("Telegram Bot : {firstname}, @{usrname}, id:{id},", info.User.FirstName ?? "[NULL]", info.User.Username ?? "[NULL]", info.User.Id);
logger.LogHandlers(handlers);
}
botHost.AddLoggingAdapter();
botHost.SetBotCommands();
return botHost;
}
private static bool TryFindWTelegramBotClient(this IServiceProvider services)
{
return services.GetServices<IHostedService>().Any(s => s is HostedWideBotUpdateReceiver);
}
}
@@ -0,0 +1,31 @@
using Telegram.Bot;
using WTelegram;
namespace Telegrator;
/// <summary>
/// Represents configuration options for initializing and customizing the behavior of a WideBot instance.
/// </summary>
/// <remarks>Use this class to specify required API credentials, optional proxy settings, update handling
/// preferences, and SQL command detection for WideBot. All required properties must be set before using the options
/// with a WideBot instance.
/// </remarks>
public class WideBotOptions
{
/// <inheritdoc cref="WTelegramBotClientOptions.ApiId"/>
public required int ApiId { get; set; }
/// <inheritdoc cref="WTelegramBotClientOptions.ApiHash"/>
public required string ApiHash { get; set; }
/// <inheritdoc cref="WTelegramBotClientOptions.MTProxy"/>
public string? MTProxy { get; set; }
/// <inheritdoc cref="WTelegramBotClientOptions.SqlCommands"/>
public SqlCommands SqlCommands { get; set; } = WTelegram.SqlCommands.Detect;
/// <summary>
/// Gets or sets a value indicating whether pending updates should be discarded.
/// </summary>
public bool DropPendingUpdates { get; set; }
}
@@ -10,3 +10,4 @@ using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("Usage", "CA2254")] [assembly: SuppressMessage("Usage", "CA2254")]
[assembly: SuppressMessage("Maintainability", "CA1510")] [assembly: SuppressMessage("Maintainability", "CA1510")]
[assembly: SuppressMessage("Style", "IDE0270")] [assembly: SuppressMessage("Style", "IDE0270")]
[assembly: SuppressMessage("Roslynator", "RCS1037")]
@@ -6,7 +6,4 @@ namespace Telegrator.Hosting;
/// <summary> /// <summary>
/// Represents a hosted telegram bots and services builder that helps manage configuration, logging, lifetime, and more. /// Represents a hosted telegram bots and services builder that helps manage configuration, logging, lifetime, and more.
/// </summary> /// </summary>
public interface ITelegramBotHostBuilder : IHostApplicationBuilder, ICollectingProvider public interface ITelegramBotHostBuilder : IHostApplicationBuilder, ICollectingProvider;
{
}
@@ -1,114 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Telegrator.Core;
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>
/// This application's logger
/// </summary>
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)
{
// Registering this host in services for easy access
hostApplicationBuilder.Services.AddSingleton<ITelegratorBot>(this);
// Building proxy hoster
_innerHost = hostApplicationBuilder.Build();
// Reruesting services for this host
_updateRouter = Services.GetRequiredService<IUpdateRouter>();
_logger = Services.GetRequiredService<ILogger<TelegramBotHost>>();
}
/// <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);
return builder;
}
/// <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);
return builder;
}
/// <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);
}
/// <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(settings);
return new TelegramBotHostBuilder(innerBuilder);
}
/// <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;
}
}
@@ -11,7 +11,7 @@ namespace Telegrator.Hosting;
/// <inheritdoc/> /// <inheritdoc/>
public class TelegramBotHostBuilder : ITelegramBotHostBuilder public class TelegramBotHostBuilder : ITelegramBotHostBuilder
{ {
private readonly HostApplicationBuilder _innerBuilder; private readonly IHostApplicationBuilder _innerBuilder;
internal IHandlersCollection _handlers = null!; internal IHandlersCollection _handlers = null!;
/// <inheritdoc/> /// <inheritdoc/>
@@ -30,7 +30,7 @@ public class TelegramBotHostBuilder : ITelegramBotHostBuilder
public IHostEnvironment Environment => _innerBuilder.Environment; public IHostEnvironment Environment => _innerBuilder.Environment;
/// <inheritdoc/> /// <inheritdoc/>
public IDictionary<object, object> Properties => ((IHostApplicationBuilder)_innerBuilder).Properties; public IDictionary<object, object> Properties => _innerBuilder.Properties;
/// <inheritdoc/> /// <inheritdoc/>
public IMetricsBuilder Metrics => _innerBuilder.Metrics; public IMetricsBuilder Metrics => _innerBuilder.Metrics;
@@ -39,7 +39,7 @@ public class TelegramBotHostBuilder : ITelegramBotHostBuilder
/// Initializes a new instance of the <see cref="TelegramBotHostBuilder"/> class. /// Initializes a new instance of the <see cref="TelegramBotHostBuilder"/> class.
/// </summary> /// </summary>
/// <param name="hostApplicationBuilder"></param> /// <param name="hostApplicationBuilder"></param>
public TelegramBotHostBuilder(HostApplicationBuilder hostApplicationBuilder) public TelegramBotHostBuilder(IHostApplicationBuilder hostApplicationBuilder)
{ {
_innerBuilder = hostApplicationBuilder ?? throw new ArgumentNullException(nameof(hostApplicationBuilder)); _innerBuilder = hostApplicationBuilder ?? throw new ArgumentNullException(nameof(hostApplicationBuilder));
} }
@@ -49,23 +49,12 @@ public class TelegramBotHostBuilder : ITelegramBotHostBuilder
/// </summary> /// </summary>
/// <param name="hostApplicationBuilder"></param> /// <param name="hostApplicationBuilder"></param>
/// <param name="handlers"></param> /// <param name="handlers"></param>
public TelegramBotHostBuilder(HostApplicationBuilder hostApplicationBuilder, IHandlersCollection handlers) public TelegramBotHostBuilder(IHostApplicationBuilder hostApplicationBuilder, IHandlersCollection handlers)
{ {
_innerBuilder = hostApplicationBuilder ?? throw new ArgumentNullException(nameof(hostApplicationBuilder)); _innerBuilder = hostApplicationBuilder ?? throw new ArgumentNullException(nameof(hostApplicationBuilder));
_handlers = handlers ?? throw new ArgumentNullException(nameof(handlers)); _handlers = handlers ?? throw new ArgumentNullException(nameof(handlers));
} }
/// <summary>
/// Builds the host.
/// </summary>
/// <returns></returns>
public TelegramBotHost Build()
{
TelegramBotHost host = new TelegramBotHost(_innerBuilder);
host.UseTelegrator();
return host;
}
/// <inheritdoc/> /// <inheritdoc/>
public void ConfigureContainer<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory, Action<TContainerBuilder>? configure = null) where TContainerBuilder : notnull public void ConfigureContainer<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory, Action<TContainerBuilder>? configure = null) where TContainerBuilder : notnull
{ {
@@ -32,11 +32,13 @@ public class MicrosoftLoggingAdapter : ITelegratorLogger
if (exception != null) if (exception != null)
{ {
_logger.Log(msLogLevel, default, message, exception, (str, exc) => string.Format("{0} : {1}", str, exc)); _logger.Log(msLogLevel, default, message, exception,
(str, exc) => string.Format("{0} : {1}", str, exc));
} }
else else
{ {
_logger.Log(msLogLevel, default, message, null, (str, _) => str); _logger.Log(msLogLevel, default, message, null,
(str, _) => str);
} }
} }
} }
@@ -5,9 +5,8 @@ using Telegram.Bot.Polling;
using Telegram.Bot.Types; using Telegram.Bot.Types;
using Telegrator.Core; using Telegrator.Core;
using Telegrator.Core.States; using Telegrator.Core.States;
using Telegrator.Mediation;
namespace Telegrator.Polling; namespace Telegrator.Mediation;
/// <inheritdoc/> /// <inheritdoc/>
public class HostUpdateRouter : UpdateRouter public class HostUpdateRouter : UpdateRouter
@@ -4,12 +4,11 @@ using Microsoft.Extensions.Options;
using Telegram.Bot; using Telegram.Bot;
using Telegram.Bot.Polling; using Telegram.Bot.Polling;
using Telegrator.Core; using Telegrator.Core;
using Telegrator.Mediation;
namespace Telegrator.Polling; namespace Telegrator.Mediation;
/// <summary> /// <summary>
/// Service for receiving updates for Hosted telegram bots /// Service for receiving updates for Hosted telegram botsand queuing them to router
/// </summary> /// </summary>
/// <param name="botClient"></param> /// <param name="botClient"></param>
/// <param name="updateRouter"></param> /// <param name="updateRouter"></param>
@@ -26,7 +25,8 @@ public class HostedUpdateReceiver(ITelegramBotClient botClient, IUpdateRouter up
logger.LogInformation("Starting receiving updates via long-polling"); logger.LogInformation("Starting receiving updates via long-polling");
_receiverOptions.AllowedUpdates = _updateRouter.HandlersProvider.AllowedTypes.ToArray(); _receiverOptions.AllowedUpdates = _updateRouter.HandlersProvider.AllowedTypes.ToArray();
botClient.DeleteWebhook(options.Value.DropPendingUpdates).Wait(); botClient.DeleteWebhook(options.Value.DropPendingUpdates, cancellationToken: stoppingToken)
.ConfigureAwait(false).GetAwaiter().GetResult();
DefaultUpdateReceiver updateReceiver = new DefaultUpdateReceiver(botClient, _receiverOptions); DefaultUpdateReceiver updateReceiver = new DefaultUpdateReceiver(botClient, _receiverOptions);
await updateReceiver.ReceiveAsync(_updateRouter, stoppingToken).ConfigureAwait(false); await updateReceiver.ReceiveAsync(_updateRouter, stoppingToken).ConfigureAwait(false);
@@ -17,41 +17,60 @@ public class HostHandlersCollection(IServiceCollection hostServiceColletion, Tel
{ {
switch (descriptor.Type) switch (descriptor.Type)
{ {
default:
throw new Exception("Unknown descriptor type");
case DescriptorType.General: case DescriptorType.General:
{ {
if (descriptor.InstanceFactory != null) if (descriptor.InstanceFactory != null)
{
Services.AddScoped(descriptor.HandlerType, _ => descriptor.InstanceFactory.Invoke()); Services.AddScoped(descriptor.HandlerType, _ => descriptor.InstanceFactory.Invoke());
else break;
Services.AddScoped(descriptor.HandlerType); }
Services.AddScoped(descriptor.HandlerType);
break; break;
} }
case DescriptorType.Keyed: case DescriptorType.Keyed:
{ {
if (descriptor.InstanceFactory != null) if (descriptor.InstanceFactory != null)
{
Services.AddKeyedScoped(descriptor.HandlerType, descriptor.ServiceKey, (_, _) => descriptor.InstanceFactory.Invoke()); Services.AddKeyedScoped(descriptor.HandlerType, descriptor.ServiceKey, (_, _) => descriptor.InstanceFactory.Invoke());
else break;
Services.AddKeyedScoped(descriptor.HandlerType, descriptor.ServiceKey); }
Services.AddKeyedScoped(descriptor.HandlerType, descriptor.ServiceKey);
break; break;
} }
case DescriptorType.Singleton: case DescriptorType.Singleton:
{ {
Services.AddSingleton(descriptor.HandlerType, descriptor.SingletonInstance ?? (descriptor.InstanceFactory != null if (descriptor.SingletonInstance != null)
? descriptor.InstanceFactory.Invoke() {
: throw new Exception())); Services.AddSingleton(descriptor.HandlerType, descriptor.SingletonInstance);
break;
}
if (descriptor.InstanceFactory == null)
throw new InvalidOperationException("Singleton handler descriptor without singleton instance should implement `InstanceFactory`");
Services.AddSingleton(descriptor.HandlerType, descriptor.InstanceFactory.Invoke());
break; break;
} }
case DescriptorType.Implicit: case DescriptorType.Implicit:
{ {
Services.AddKeyedSingleton(descriptor.HandlerType, descriptor.ServiceKey, descriptor.SingletonInstance ?? (descriptor.InstanceFactory != null if (descriptor.SingletonInstance != null)
? descriptor.InstanceFactory.Invoke() {
: throw new Exception())); Services.AddKeyedSingleton(descriptor.HandlerType, descriptor.ServiceKey, descriptor.SingletonInstance);
break;
}
if (descriptor.InstanceFactory == null)
throw new InvalidOperationException("Implicit handler descriptor without singleton instance should implement `InstanceFactory`");
Services.AddKeyedSingleton(descriptor.HandlerType, descriptor.ServiceKey, descriptor.InstanceFactory.Invoke());
break; break;
} }
} }
@@ -13,9 +13,12 @@
<GenerateDocumentationFile>True</GenerateDocumentationFile> <GenerateDocumentationFile>True</GenerateDocumentationFile>
<EnableNETAnalyzers>True</EnableNETAnalyzers> <EnableNETAnalyzers>True</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild> <EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
<IncludeSymbols>True</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<SignAssembly>False</SignAssembly>
<Title>Telegrator.Hosting</Title> <Title>Telegrator.Hosting</Title>
<Version>1.16.9</Version> <Version>1.17.1</Version>
<Authors>Rikitav Tim4ik</Authors> <Authors>Rikitav Tim4ik</Authors>
<Company>Rikitav Tim4ik</Company> <Company>Rikitav Tim4ik</Company>
<RepositoryUrl>https://github.com/Rikitav/Telegrator</RepositoryUrl> <RepositoryUrl>https://github.com/Rikitav/Telegrator</RepositoryUrl>
+57 -23
View File
@@ -15,7 +15,7 @@ using Telegrator.Core.Descriptors;
using Telegrator.Core.States; using Telegrator.Core.States;
using Telegrator.Hosting; using Telegrator.Hosting;
using Telegrator.Logging; using Telegrator.Logging;
using Telegrator.Polling; using Telegrator.Mediation;
using Telegrator.Providers; using Telegrator.Providers;
using Telegrator.States; using Telegrator.States;
@@ -34,20 +34,7 @@ public static class HostBuilderExtensions
/// <summary> /// <summary>
/// Replaces TelegramBotHostBuilder. Configures DI, options, and handlers. /// Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
/// </summary> /// </summary>
public static ITelegramBotHostBuilder AddTelegrator(this ITelegramBotHostBuilder builder, TelegratorOptions? options = null, IHandlersCollection? handlers = null, Action<ITelegramBotHostBuilder>? action = null) public static IHostApplicationBuilder AddTelegrator(this IHostApplicationBuilder builder, TelegratorOptions? options = null, IHandlersCollection? handlers = null, Action<ITelegramBotHostBuilder>? action = null)
{
AddTelegratorInternal(builder.Services, builder.Configuration, builder.Properties, ref handlers, options);
if (builder is TelegramBotHostBuilder telegramBotHostBuilder)
telegramBotHostBuilder._handlers = handlers;
action?.Invoke(builder);
return builder;
}
/// <summary>
/// Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
/// </summary>
public static IHostApplicationBuilder AddTelegrator(this HostApplicationBuilder builder, TelegratorOptions? options = null, IHandlersCollection? handlers = null, Action<ITelegramBotHostBuilder>? action = null)
{ {
AddTelegratorInternal(builder.Services, builder.Configuration, ((IHostApplicationBuilder)builder).Properties, ref handlers, options); AddTelegratorInternal(builder.Services, builder.Configuration, ((IHostApplicationBuilder)builder).Properties, ref handlers, options);
action?.Invoke(new TelegramBotHostBuilder(builder, handlers)); action?.Invoke(new TelegramBotHostBuilder(builder, handlers));
@@ -72,6 +59,16 @@ public static class HostBuilderExtensions
return builder; return builder;
} }
/// <summary>
/// Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
/// </summary>
public static IHostBuilder AddTelegrator(this IHostBuilder builder, TelegratorOptions? options = null, IHandlersCollection? handlers = null, Action<IHandlersCollection>? action = null)
{
builder.ConfigureServices((ctx, sp) => AddTelegratorInternal(sp, ctx.Configuration, builder.Properties, ref handlers, options));
action?.Invoke(handlers!); // AddTelegratorInternal initializes `handlers`
return builder;
}
/// <summary> /// <summary>
/// Replaces TelegramBotHostBuilder. Configures DI, options, and handlers. /// Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
/// </summary> /// </summary>
@@ -81,7 +78,7 @@ public static class HostBuilderExtensions
{ {
options = configuration.GetSection(nameof(TelegratorOptions)).Get<TelegratorOptions>(); options = configuration.GetSection(nameof(TelegratorOptions)).Get<TelegratorOptions>();
if (options == null) if (options == null)
throw new MissingMemberException("Auto configuration disabled, yet no options of type 'TelegratorOptions' wasn't registered. This configuration is runtime required!"); throw new MissingMemberException("Auto configuration disabled, yet no options of type 'TelegratorOptions' was registered. This configuration is runtime required!");
} }
CancellationTokenSource globallCancell = new CancellationTokenSource(); CancellationTokenSource globallCancell = new CancellationTokenSource();
@@ -103,11 +100,11 @@ public static class HostBuilderExtensions
services.AddSingleton(handlers); services.AddSingleton(handlers);
properties.Add(HandlersCollectionPropertyKey, handlers); properties.Add(HandlersCollectionPropertyKey, handlers);
if (!services.Any(srvc => srvc.ImplementationType == typeof(IOptions<ReceiverOptions>))) if (!services.Any(srvc => srvc.ServiceType == typeof(IOptions<ReceiverOptions>)))
{ {
ReceiverOptions? receiverOptions = configuration.GetSection(nameof(ReceiverOptions)).Get<ReceiverOptions>(); ReceiverOptions? receiverOptions = configuration.GetSection(nameof(ReceiverOptions)).Get<ReceiverOptions>();
if (receiverOptions == null) if (receiverOptions == null)
throw new MissingMemberException("Auto configuration disabled, yet no options of type 'ReceiverOptions' wasn't registered. This configuration is runtime required!"); throw new MissingMemberException("Auto configuration disabled, yet no options of type 'ReceiverOptions' was registered. This configuration is runtime required!");
services.AddSingleton(Options.Create(receiverOptions)); services.AddSingleton(Options.Create(receiverOptions));
} }
@@ -130,8 +127,34 @@ public static class HostBuilderExtensions
/// Contains extensions for <see cref="IServiceCollection"/> /// Contains extensions for <see cref="IServiceCollection"/>
/// Provides method to configure Telegram Bot Host /// Provides method to configure Telegram Bot Host
/// </summary> /// </summary>
public static class ServicesCollectionExtensions public static class HostServicesCollectionExtensions
{ {
/// <summary>
/// Adds TelegramBotClientOptions to services
/// </summary>
/// <param name="services"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IServiceCollection ConfigureTelegram(this IServiceCollection services, TelegramBotClientOptions options)
{
services.RemoveAll<IOptions<TelegramBotClientOptions>>();
services.AddSingleton(Options.Create(options));
return services;
}
/// <summary>
/// Adds ReceiverOptions to services
/// </summary>
/// <param name="services"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IServiceCollection ConfigureReceiver(this IServiceCollection services, ReceiverOptions options)
{
services.RemoveAll<IOptions<ReceiverOptions>>();
services.AddSingleton(Options.Create(options));
return services;
}
/// <summary> /// <summary>
/// Registers <see cref="IStateStorage"/> service /// Registers <see cref="IStateStorage"/> service
/// </summary> /// </summary>
@@ -145,7 +168,7 @@ public static class ServicesCollectionExtensions
} }
/// <summary> /// <summary>
/// Registers <see cref="TelegramBotHost"/> default services /// Registers <see cref="Telegrator"/> default services
/// </summary> /// </summary>
/// <param name="services"></param> /// <param name="services"></param>
/// <returns></returns> /// <returns></returns>
@@ -167,6 +190,9 @@ public static class ServicesCollectionExtensions
/// <returns></returns> /// <returns></returns>
public static IServiceCollection AddTelegramReceiver(this IServiceCollection services) public static IServiceCollection AddTelegramReceiver(this IServiceCollection services)
{ {
services.RemoveAll<ITelegramBotClient>();
services.RemoveAll<HostedUpdateReceiver>();
services.AddHttpClient<ITelegramBotClient>("tgreceiver").RemoveAllLoggers().AddTypedClient(TypedTelegramBotClientFactory); services.AddHttpClient<ITelegramBotClient>("tgreceiver").RemoveAllLoggers().AddTypedClient(TypedTelegramBotClientFactory);
services.AddHostedService<HostedUpdateReceiver>(); services.AddHostedService<HostedUpdateReceiver>();
return services; return services;
@@ -200,11 +226,14 @@ public static class TelegramBotHostExtensions
if (logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Information)) if (logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Information))
{ {
logger.LogInformation("Telegrator Bot .NET Host started"); logger.LogInformation("Telegrator Bot Host started (Generic Host)");
logger.LogInformation("Receiving mode : LONG-POLLING");
logger.LogInformation("Telegram Bot : {firstname}, @{usrname}, id:{id},", info.User.FirstName ?? "[NULL]", info.User.Username ?? "[NULL]", info.User.Id); logger.LogInformation("Telegram Bot : {firstname}, @{usrname}, id:{id},", info.User.FirstName ?? "[NULL]", info.User.Username ?? "[NULL]", info.User.Id);
logger.LogHandlers(handlers); logger.LogHandlers(handlers);
} }
botHost.AddLoggingAdapter();
botHost.SetBotCommands();
return botHost; return botHost;
} }
@@ -219,7 +248,12 @@ public static class TelegramBotHostExtensions
IUpdateRouter router = botHost.Services.GetRequiredService<IUpdateRouter>(); IUpdateRouter router = botHost.Services.GetRequiredService<IUpdateRouter>();
IEnumerable<BotCommand> aliases = router.HandlersProvider.GetBotCommands(); IEnumerable<BotCommand> aliases = router.HandlersProvider.GetBotCommands();
client.SetMyCommands(aliases).Wait(); if (aliases.Any())
{
client.SetMyCommands(aliases)
.ConfigureAwait(false).GetAwaiter().GetResult();
}
return botHost; return botHost;
} }
@@ -255,7 +289,7 @@ public static class LoggerExtensions
StringBuilder logBuilder = new StringBuilder("Registered handlers : "); StringBuilder logBuilder = new StringBuilder("Registered handlers : ");
if (!handlers.Keys.Any()) if (!handlers.Keys.Any())
throw new Exception(); throw new Exception("No update types were registered");
foreach (UpdateType updateType in handlers.Keys) foreach (UpdateType updateType in handlers.Keys)
{ {
View File
@@ -2,7 +2,31 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework> <TargetFramework>netstandard2.1</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<RootNamespace>Telegrator</RootNamespace>
<BaseOutputPath>..\..\bin</BaseOutputPath>
<DocumentationFile>..\..\docs\$(AssemblyName).xml</DocumentationFile>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<EnableNETAnalyzers>True</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
<IncludeSymbols>True</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<SignAssembly>False</SignAssembly>
<Title>Telegrator.Localized</Title>
<Version>1.17.1</Version>
<Authors>Rikitav Tim4ik</Authors>
<Company>Rikitav Tim4ik</Company>
<RepositoryUrl>https://github.com/Rikitav/Telegrator</RepositoryUrl>
<PackageTags>telegram;bot;mediator;attributes;aspect;hosting;host;framework;easy;simple;handlers</PackageTags>
<PackageIcon>telegrator_nuget.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -13,4 +37,10 @@
<ProjectReference Include="..\Telegrator\Telegrator.csproj" /> <ProjectReference Include="..\Telegrator\Telegrator.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include=".\README.md" Pack="True" PackagePath="\" />
<None Include="..\..\LICENSE" Pack="True" PackagePath="\" />
<None Include="..\..\resources\telegrator_nuget.png" Pack="True" PackagePath="\" />
</ItemGroup>
</Project> </Project>
@@ -125,7 +125,8 @@ public sealed class DescriptorFiltersSet
if (!anyErrors) if (!anyErrors)
return Result.Ok(); return Result.Ok();
return formReport ? Result.Next() : Result.Fault(); return formReport
? Result.Next() : Result.Fault();
} }
private static bool ExecuteFilter<T>(IFilter<T> filter, FilterExecutionContext<T> context, out Exception? exception) where T : class private static bool ExecuteFilter<T>(IFilter<T> filter, FilterExecutionContext<T> context, out Exception? exception) where T : class
@@ -1,4 +1,7 @@
using System.ComponentModel; using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection; using System.Reflection;
using Telegram.Bot.Types; using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums; using Telegram.Bot.Types.Enums;
@@ -21,6 +24,11 @@ public static class HandlerInspector
/// <returns></returns> /// <returns></returns>
public static string? GetDisplayName(MemberInfo handlerType) public static string? GetDisplayName(MemberInfo handlerType)
{ {
if (handlerType == null)
{
throw new ArgumentNullException(nameof(handlerType));
}
return handlerType.GetCustomAttribute<DisplayNameAttribute>()?.DisplayName; return handlerType.GetCustomAttribute<DisplayNameAttribute>()?.DisplayName;
} }
@@ -31,11 +39,26 @@ public static class HandlerInspector
/// <returns>The handler attribute.</returns> /// <returns>The handler attribute.</returns>
public static UpdateHandlerAttributeBase GetHandlerAttribute(MemberInfo handlerType) public static UpdateHandlerAttributeBase GetHandlerAttribute(MemberInfo handlerType)
{ {
// Getting polling handler attribute if (handlerType == null)
IEnumerable<UpdateHandlerAttributeBase> handlerAttrs = handlerType.GetCustomAttributes<UpdateHandlerAttributeBase>(); {
throw new ArgumentNullException(nameof(handlerType));
}
// List<UpdateHandlerAttributeBase> handlerAttrs = handlerType.GetCustomAttributes<UpdateHandlerAttributeBase>().ToList();
return handlerAttrs.Single();
if (handlerAttrs.Count == 0)
{
throw new InvalidOperationException(
$"Failed to register handler '{handlerType.Name}': Missing required attribute derived from '{nameof(UpdateHandlerAttributeBase)}'.");
}
if (handlerAttrs.Count > 1)
{
throw new InvalidOperationException(
$"Failed to register handler '{handlerType.Name}': Multiple handler attributes found. A handler must have exactly one attribute derived from '{nameof(UpdateHandlerAttributeBase)}'.");
}
return handlerAttrs[0];
} }
/// <summary> /// <summary>
@@ -45,10 +68,16 @@ public static class HandlerInspector
/// <returns>The state keeper attribute, or null if not present.</returns> /// <returns>The state keeper attribute, or null if not present.</returns>
public static IFilter<Update>? GetStateKeeperAttribute(MemberInfo handlerType) public static IFilter<Update>? GetStateKeeperAttribute(MemberInfo handlerType)
{ {
// Getting polling handler attribute if (handlerType == null)
Attribute stateAttr = handlerType.GetCustomAttribute(typeof(StateAttribute<,>)); throw new ArgumentNullException(nameof(handlerType));
Attribute? stateAttr = handlerType.GetCustomAttributes()
.FirstOrDefault(attr =>
{
Type type = attr.GetType();
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(StateAttribute<,>);
});
//
return stateAttr as IFilter<Update>; return stateAttr as IFilter<Update>;
} }
@@ -60,12 +89,19 @@ public static class HandlerInspector
/// <returns>An enumerable of filter attributes.</returns> /// <returns>An enumerable of filter attributes.</returns>
public static IEnumerable<IFilter<Update>> GetFilterAttributes(MemberInfo handlerType, UpdateType validUpdType) public static IEnumerable<IFilter<Update>> GetFilterAttributes(MemberInfo handlerType, UpdateType validUpdType)
{ {
// if (handlerType == null)
IEnumerable<UpdateFilterAttributeBase> filters = handlerType.GetCustomAttributes<UpdateFilterAttributeBase>(); throw new ArgumentNullException(nameof(handlerType));
// List<UpdateFilterAttributeBase> filters = handlerType.GetCustomAttributes<UpdateFilterAttributeBase>().ToList();
if (filters.Any(filterAttr => !filterAttr.AllowedTypes.Contains(validUpdType)))
throw new InvalidOperationException(); UpdateFilterAttributeBase? invalidFilter = filters.FirstOrDefault(f => !f.AllowedTypes.Contains(validUpdType));
if (invalidFilter != null)
{
string allowedTypesStr = string.Join(", ", invalidFilter.AllowedTypes);
throw new InvalidOperationException(
$"Filter conflict on handler '{handlerType.Name}': The filter '{invalidFilter.GetType().Name}' " +
$"does not support update type '{validUpdType}'. Allowed types: [{allowedTypesStr}].");
}
UpdateFilterAttributeBase? lastFilterAttribute = null; UpdateFilterAttributeBase? lastFilterAttribute = null;
foreach (UpdateFilterAttributeBase filterAttribute in filters) foreach (UpdateFilterAttributeBase filterAttribute in filters)
@@ -78,7 +114,6 @@ public static class HandlerInspector
else else
{ {
lastFilterAttribute = filterAttribute; lastFilterAttribute = filterAttribute;
continue;
} }
} }
} }
@@ -91,8 +126,24 @@ public static class HandlerInspector
/// <returns>A <see cref="DescriptorAspectsSet"/> containing the aspects configuration.</returns> /// <returns>A <see cref="DescriptorAspectsSet"/> containing the aspects configuration.</returns>
public static DescriptorAspectsSet GetAspects(Type handlerType) public static DescriptorAspectsSet GetAspects(Type handlerType)
{ {
Type? typedPre = handlerType.GetCustomAttribute(typeof(BeforeExecutionAttribute<>))?.GetType().GetGenericArguments()[0]; if (handlerType == null)
Type? typedPost = handlerType.GetCustomAttribute(typeof(AfterExecutionAttribute<>))?.GetType().GetGenericArguments()[0]; throw new ArgumentNullException(nameof(handlerType));
Type? typedPre = GetGenericArgumentFromOpenGenericAttribute(handlerType, typeof(BeforeExecutionAttribute<>));
Type? typedPost = GetGenericArgumentFromOpenGenericAttribute(handlerType, typeof(AfterExecutionAttribute<>));
return new DescriptorAspectsSet(typedPre, typedPost); return new DescriptorAspectsSet(typedPre, typedPost);
} }
private static Type? GetGenericArgumentFromOpenGenericAttribute(Type handlerType, Type openGenericAttributeType)
{
Attribute? attribute = handlerType.GetCustomAttributes()
.FirstOrDefault(attr =>
{
Type type = attr.GetType();
return type.IsGenericType && type.GetGenericTypeDefinition() == openGenericAttributeType;
});
return attribute?.GetType().GetGenericArguments().FirstOrDefault();
}
} }
@@ -56,7 +56,7 @@ public abstract class UpdateHandlerBase(UpdateType handlingUpdateType) : IUpdate
.ExecutePre(this, container, cancellationToken) .ExecutePre(this, container, cancellationToken)
.ConfigureAwait(false); .ConfigureAwait(false);
if (!preResult.Positive) if (!preResult.Success)
return preResult; return preResult;
} }
catch (NotImplementedException) catch (NotImplementedException)
@@ -69,7 +69,7 @@ public abstract class UpdateHandlerBase(UpdateType handlingUpdateType) : IUpdate
{ {
// Executing handler // Executing handler
Result execResult = await ExecuteInternal(container, cancellationToken).ConfigureAwait(false); Result execResult = await ExecuteInternal(container, cancellationToken).ConfigureAwait(false);
if (!execResult.Positive) if (!execResult.Success)
return execResult; return execResult;
} }
catch (NotImplementedException) catch (NotImplementedException)
@@ -86,7 +86,7 @@ public abstract class UpdateHandlerBase(UpdateType handlingUpdateType) : IUpdate
.ExecutePost(this, container, cancellationToken) .ExecutePost(this, container, cancellationToken)
.ConfigureAwait(false); .ConfigureAwait(false);
if (!postResult.Positive) if (!postResult.Success)
return postResult; return postResult;
} }
} }
@@ -166,7 +166,7 @@ public abstract class UpdateHandlerBase(UpdateType handlingUpdateType) : IUpdate
/// <returns></returns> /// <returns></returns>
public virtual Task<Result> FiltersFallback(FiltersFallbackReport report, ITelegramBotClient client, CancellationToken cancellationToken = default) public virtual Task<Result> FiltersFallback(FiltersFallbackReport report, ITelegramBotClient client, CancellationToken cancellationToken = default)
{ {
return Task.FromResult(Result.Ok()); return Task.FromResult(Result.Next());
} }
/// <inheritdoc/> /// <inheritdoc/>
+1
View File
@@ -10,3 +10,4 @@ using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("Style", "IDE0057")] [assembly: SuppressMessage("Style", "IDE0057")]
[assembly: SuppressMessage("Style", "IDE0270")] [assembly: SuppressMessage("Style", "IDE0270")]
[assembly: SuppressMessage("Roslynator", "RCS1037")] [assembly: SuppressMessage("Roslynator", "RCS1037")]
[assembly: SuppressMessage("Roslynator", "RCS1227")]
+10 -1
View File
@@ -1,4 +1,5 @@
using Telegrator.Core; using Telegram.Bot.Polling;
using Telegrator.Core;
namespace Telegrator; namespace Telegrator;
@@ -12,4 +13,12 @@ public interface ITelegratorBot
/// Gets the update router for handling incoming updates. /// Gets the update router for handling incoming updates.
/// </summary> /// </summary>
public IUpdateRouter UpdateRouter { get; } public IUpdateRouter UpdateRouter { get; }
/// <summary>
/// Initializes the update router and begins polling for updates asynchronously.
/// </summary>
/// <param name="receiverOptions">Optional receiver options for configuring update polling.</param>
/// <param name="cancellationToken">The cancellation token to stop receiving updates.</param>
/// <returns></returns>
Task StartReceivingAsync(ReceiverOptions? receiverOptions = null, CancellationToken cancellationToken = default);
} }
+15 -28
View File
@@ -19,27 +19,22 @@ namespace Telegrator.Mediation;
/// </summary> /// </summary>
public class UpdateRouter : IUpdateRouter public class UpdateRouter : IUpdateRouter
{ {
private readonly TelegratorOptions _options;
private readonly IHandlersProvider _handlersProvider;
private readonly IAwaitingProvider _awaitingProvider;
private readonly IStateStorage _stateStorage;
private readonly IUpdateHandlersPool _HandlersPool;
private readonly ITelegramBotInfo _botInfo; private readonly ITelegramBotInfo _botInfo;
/// <inheritdoc/> /// <inheritdoc/>
public IHandlersProvider HandlersProvider => _handlersProvider; public TelegratorOptions Options { get; }
/// <inheritdoc/> /// <inheritdoc/>
public IAwaitingProvider AwaitingProvider => _awaitingProvider; public IHandlersProvider HandlersProvider { get; }
/// <inheritdoc/> /// <inheritdoc/>
public IStateStorage StateStorage => _stateStorage; public IAwaitingProvider AwaitingProvider { get; }
/// <inheritdoc/> /// <inheritdoc/>
public TelegratorOptions Options => _options; public IStateStorage StateStorage { get; }
/// <inheritdoc/> /// <inheritdoc/>
public IUpdateHandlersPool HandlersPool => _HandlersPool; public IUpdateHandlersPool HandlersPool { get; }
/// <inheritdoc/> /// <inheritdoc/>
public IRouterExceptionHandler? ExceptionHandler { get; set; } public IRouterExceptionHandler? ExceptionHandler { get; set; }
@@ -57,11 +52,11 @@ public class UpdateRouter : IUpdateRouter
/// <param name="botInfo"></param> /// <param name="botInfo"></param>
public UpdateRouter(IHandlersProvider handlersProvider, IAwaitingProvider awaitingProvider, IStateStorage stateStorage, TelegratorOptions options, ITelegramBotInfo botInfo) public UpdateRouter(IHandlersProvider handlersProvider, IAwaitingProvider awaitingProvider, IStateStorage stateStorage, TelegratorOptions options, ITelegramBotInfo botInfo)
{ {
_options = options; Options = options;
_handlersProvider = handlersProvider; HandlersProvider = handlersProvider;
_awaitingProvider = awaitingProvider; AwaitingProvider = awaitingProvider;
_stateStorage = stateStorage; StateStorage = stateStorage;
_HandlersPool = new UpdateHandlersPool(this, _options, _options.GlobalCancellationToken); HandlersPool = new UpdateHandlersPool(this, Options, Options.GlobalCancellationToken);
_botInfo = botInfo; _botInfo = botInfo;
} }
@@ -102,11 +97,8 @@ public class UpdateRouter : IUpdateRouter
Result? lastResult = null; Result? lastResult = null;
foreach (DescribedHandlerDescriptor handlerInfo in GetHandlers(AwaitingProvider, botClient, update, cancellationToken)) foreach (DescribedHandlerDescriptor handlerInfo in GetHandlers(AwaitingProvider, botClient, update, cancellationToken))
{ {
if (lastResult?.NextType != null) if (lastResult?.NextType is not null && lastResult?.NextType != handlerInfo.From.HandlerType)
{
if (lastResult.NextType != handlerInfo.From.HandlerType)
continue; continue;
}
// Enqueuing found awiting handlers // Enqueuing found awiting handlers
await HandlersPool.Enqueue(handlerInfo); await HandlersPool.Enqueue(handlerInfo);
@@ -116,7 +108,7 @@ public class UpdateRouter : IUpdateRouter
if (lastResult == null) if (lastResult == null)
break; // Smth went horribly wrong, better to stop routing break; // Smth went horribly wrong, better to stop routing
if (lastResult != null && !lastResult.RouteNext) if (!lastResult.RouteNext)
break; break;
TelegratorLogging.LogTrace("Handler '{0}' requested route continuation (Update {1})", handlerInfo.DisplayString, handlerInfo.HandlingUpdate.Id); TelegratorLogging.LogTrace("Handler '{0}' requested route continuation (Update {1})", handlerInfo.DisplayString, handlerInfo.HandlingUpdate.Id);
@@ -132,11 +124,8 @@ public class UpdateRouter : IUpdateRouter
// Queuing reagular handlers for execution // Queuing reagular handlers for execution
foreach (DescribedHandlerDescriptor handlerInfo in GetHandlers(HandlersProvider, botClient, update, cancellationToken)) foreach (DescribedHandlerDescriptor handlerInfo in GetHandlers(HandlersProvider, botClient, update, cancellationToken))
{ {
if (lastResult?.NextType != null) if (lastResult?.NextType is not null && lastResult?.NextType != handlerInfo.From.HandlerType)
{
if (lastResult.NextType != handlerInfo.From.HandlerType)
continue; continue;
}
// Enqueuing found handlers // Enqueuing found handlers
await HandlersPool.Enqueue(handlerInfo); await HandlersPool.Enqueue(handlerInfo);
@@ -146,7 +135,7 @@ public class UpdateRouter : IUpdateRouter
if (lastResult == null) if (lastResult == null)
break; // Smth went horribly wrong, better to stop routing break; // Smth went horribly wrong, better to stop routing
if (lastResult != null && !lastResult.RouteNext) if (!lastResult.RouteNext)
break; break;
TelegratorLogging.LogTrace("Handler '{0}' requested route continuation (Update {1})", handlerInfo.DisplayString, handlerInfo.HandlingUpdate.Id); TelegratorLogging.LogTrace("Handler '{0}' requested route continuation (Update {1})", handlerInfo.DisplayString, handlerInfo.HandlingUpdate.Id);
@@ -255,7 +244,7 @@ public class UpdateRouter : IUpdateRouter
breakRouting = !fallbackResult.RouteNext; breakRouting = !fallbackResult.RouteNext;
return null; return null;
} }
else if (!filtersResult.Positive) else if (!filtersResult.Success)
{ {
return null; return null;
} }
@@ -307,6 +296,4 @@ public class UpdateRouter : IUpdateRouter
TelegratorLogging.LogTrace(sb.ToString()); TelegratorLogging.LogTrace(sb.ToString());
} }
private class BreakDescribingException : Exception { }
} }
+5 -5
View File
@@ -15,12 +15,12 @@ public sealed class Result
private static readonly Result next = new Result(true, true, null); private static readonly Result next = new Result(true, true, null);
/// <summary> /// <summary>
/// Is result positive /// Tell router to stop describing
/// </summary> /// </summary>
public bool Positive { get; } public bool Success { get; }
/// <summary> /// <summary>
/// Should router search for next matching handler /// Tell router to continue describing
/// </summary> /// </summary>
public bool RouteNext { get; } public bool RouteNext { get; }
@@ -29,9 +29,9 @@ public sealed class Result
/// </summary> /// </summary>
public Type? NextType { get; } public Type? NextType { get; }
internal Result(bool positive, bool routeNext, Type? nextType) internal Result(bool success, bool routeNext, Type? nextType)
{ {
Positive = positive; Success = success;
RouteNext = routeNext; RouteNext = routeNext;
NextType = nextType; NextType = nextType;
} }
+18 -1
View File
@@ -26,6 +26,21 @@ public static partial class ColletionsExtensions
return new ReadOnlyDictionary<TKey, TValue>(dictionary); return new ReadOnlyDictionary<TKey, TValue>(dictionary);
} }
/// <summary>
/// Remove all <see langword="null"/> values and returns collection without nullable type.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <returns></returns>
public static IEnumerable<T> Squeeze<T>(this IEnumerable<T?> source)
{
foreach (T? item in source)
{
if (item is not null)
yield return item;
}
}
/// <summary> /// <summary>
/// Enumerates objects in a <paramref name="source"/> and executes an <paramref name="action"/> on each one /// Enumerates objects in a <paramref name="source"/> and executes an <paramref name="action"/> on each one
/// </summary> /// </summary>
@@ -188,7 +203,7 @@ public static partial class ReflectionExtensions
/// </summary> /// </summary>
/// <param name="type"></param> /// <param name="type"></param>
/// <returns></returns> /// <returns></returns>
public static bool IsHandlerRealization(this Type type) public static bool IsHandlerImplementation(this Type type)
=> !type.IsAbstract && type != typeof(UpdateHandlerBase) && typeof(UpdateHandlerBase).IsAssignableFrom(type); => !type.IsAbstract && type != typeof(UpdateHandlerBase) && typeof(UpdateHandlerBase).IsAssignableFrom(type);
/// <summary> /// <summary>
@@ -260,6 +275,7 @@ public static partial class StringExtensions
{ {
char[] chars = target.ToCharArray(); char[] chars = target.ToCharArray();
int index = chars.IndexOf(char.IsLetter); int index = chars.IndexOf(char.IsLetter);
chars[index] = char.ToUpper(chars[index]); chars[index] = char.ToUpper(chars[index]);
return new string(chars); return new string(chars);
} }
@@ -273,6 +289,7 @@ public static partial class StringExtensions
{ {
char[] chars = target.ToCharArray(); char[] chars = target.ToCharArray();
int index = chars.IndexOf(char.IsLetter); int index = chars.IndexOf(char.IsLetter);
chars[index] = char.ToLower(chars[index]); chars[index] = char.ToLower(chars[index]);
return new string(chars); return new string(chars);
} }
+5 -3
View File
@@ -12,9 +12,12 @@
<GenerateDocumentationFile>True</GenerateDocumentationFile> <GenerateDocumentationFile>True</GenerateDocumentationFile>
<EnableNETAnalyzers>True</EnableNETAnalyzers> <EnableNETAnalyzers>True</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild> <EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
<IncludeSymbols>True</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<SignAssembly>False</SignAssembly>
<Title>Telegrator : Telegram.Bot mediator framework</Title> <Title>Telegrator : Telegram.Bot mediator framework</Title>
<Version>1.16.9</Version> <Version>1.17.1</Version>
<Authors>Rikitav Tim4ik</Authors> <Authors>Rikitav Tim4ik</Authors>
<Company>Rikitav Tim4ik</Company> <Company>Rikitav Tim4ik</Company>
<RepositoryUrl>https://github.com/Rikitav/Telegrator</RepositoryUrl> <RepositoryUrl>https://github.com/Rikitav/Telegrator</RepositoryUrl>
@@ -23,7 +26,6 @@
<PackageIcon>telegrator_nuget.png</PackageIcon> <PackageIcon>telegrator_nuget.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile> <PackageReadmeFile>README.md</PackageReadmeFile>
<PackageLicenseFile>LICENSE</PackageLicenseFile> <PackageLicenseFile>LICENSE</PackageLicenseFile>
<UserSecretsId>b78bc62d-e49f-4ef0-b2de-ff4ceb3971af</UserSecretsId>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -33,7 +35,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Telegram.Bot" Version="22.9.6.1" /> <PackageReference Include="Telegram.Bot" Version="22.9.5.3" />
<PackageReference Include="System.Threading.Channels" Version="10.0.7" /> <PackageReference Include="System.Threading.Channels" Version="10.0.7" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.7" /> <PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.7" />
</ItemGroup> </ItemGroup>
+9 -19
View File
@@ -20,16 +20,16 @@ public class TelegratorClient : TelegramBotClient, ITelegratorBot, ICollectingPr
private IUpdateRouter? updateRouter = null; private IUpdateRouter? updateRouter = null;
/// <inheritdoc/> /// <inheritdoc/>
public TelegratorOptions Options { get; private set; } public TelegratorOptions Options { get; }
/// <inheritdoc/> /// <inheritdoc/>
public IHandlersCollection Handlers { get; private set; } public IHandlersCollection Handlers { get; }
/// <inheritdoc/> /// <inheritdoc/>
public ITelegramBotInfo BotInfo { get; private set; } public ITelegramBotInfo BotInfo { get; }
/// <inheritdoc/> /// <inheritdoc/>
public IUpdateRouter UpdateRouter { get => updateRouter ?? throw new Exception(); } public IUpdateRouter UpdateRouter => updateRouter ?? throw new InvalidOperationException("Router's not created yet. Invoke `StartReceiving` to initialize this property.");
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TelegratorClient"/> class with a bot token. /// Initializes a new instance of the <see cref="TelegratorClient"/> class with a bot token.
@@ -63,13 +63,8 @@ public class TelegratorClient : TelegramBotClient, ITelegratorBot, ICollectingPr
BotInfo = new TelegramBotInfo(this.GetMe(cancellationToken).Result); BotInfo = new TelegramBotInfo(this.GetMe(cancellationToken).Result);
} }
/// <summary> /// <inheritdoc/>
/// Starts receiving updates from Telegram. public async Task StartReceivingAsync(ReceiverOptions? receiverOptions = null, CancellationToken cancellationToken = default)
/// Initializes the update router and begins polling for updates.
/// </summary>
/// <param name="receiverOptions">Optional receiver options for configuring update polling.</param>
/// <param name="cancellationToken">The cancellation token to stop receiving updates.</param>
public void StartReceiving(ReceiverOptions? receiverOptions = null, CancellationToken cancellationToken = default)
{ {
if (Options.GlobalCancellationToken == CancellationToken.None) if (Options.GlobalCancellationToken == CancellationToken.None)
Options.GlobalCancellationToken = cancellationToken; Options.GlobalCancellationToken = cancellationToken;
@@ -78,12 +73,9 @@ public class TelegratorClient : TelegramBotClient, ITelegratorBot, ICollectingPr
AwaitingProvider awaitingProvider = new AwaitingProvider(Options); AwaitingProvider awaitingProvider = new AwaitingProvider(Options);
DefaultStateStorage stateStorage = new DefaultStateStorage(); DefaultStateStorage stateStorage = new DefaultStateStorage();
updateRouter = new UpdateRouter(handlerProvider, awaitingProvider, stateStorage, Options, BotInfo);
// Log startup
TelegratorLogging.LogInformation($"Telegrator bot starting up - BotId: {BotInfo.User.Id}, Username: {BotInfo.User.Username}, MaxParallelHandlers: {Options.MaximumParallelWorkingHandlers ?? -1}"); TelegratorLogging.LogInformation($"Telegrator bot starting up - BotId: {BotInfo.User.Id}, Username: {BotInfo.User.Username}, MaxParallelHandlers: {Options.MaximumParallelWorkingHandlers ?? -1}");
updateRouter = new UpdateRouter(handlerProvider, awaitingProvider, stateStorage, Options, BotInfo);
StartReceivingInternal(receiverOptions, cancellationToken); await StartReceivingInternal(receiverOptions, Options.GlobalCancellationToken);
} }
/// <summary> /// <summary>
@@ -92,7 +84,7 @@ public class TelegratorClient : TelegramBotClient, ITelegratorBot, ICollectingPr
/// </summary> /// </summary>
/// <param name="receiverOptions">Optional receiver options for configuring update polling.</param> /// <param name="receiverOptions">Optional receiver options for configuring update polling.</param>
/// <param name="cancellationToken">The cancellation token to stop receiving updates.</param> /// <param name="cancellationToken">The cancellation token to stop receiving updates.</param>
private async void StartReceivingInternal(ReceiverOptions? receiverOptions, CancellationToken cancellationToken) private async Task StartReceivingInternal(ReceiverOptions? receiverOptions, CancellationToken cancellationToken)
{ {
try try
{ {
@@ -115,6 +107,4 @@ public class TelegratorClient : TelegramBotClient, ITelegratorBot, ICollectingPr
TelegratorLogging.LogInformation("Telegrator bot stopped (cancelled)"); TelegratorLogging.LogInformation("Telegrator bot stopped (cancelled)");
} }
} }
} }
+41 -2
View File
@@ -1,4 +1,5 @@
using System.Reflection; using System.Reflection;
using Telegram.Bot.Polling;
using Telegram.Bot.Types; using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums; using Telegram.Bot.Types.Enums;
using Telegram.Bot.Types.Payments; using Telegram.Bot.Types.Payments;
@@ -13,6 +14,24 @@ using Telegrator.States;
namespace Telegrator; namespace Telegrator;
/// <summary>
/// Provides usefull helper methods for TelegratorBot
/// </summary>
public static class TelegratorBotExtensions
{
/// <summary>
/// Initializes the update router and begins polling for updates synchronously (Blocking calling thread).
/// </summary>
/// <param name="bot"></param>
/// <param name="receiverOptions">Optional receiver options for configuring update polling.</param>
/// <param name="cancellationToken">The cancellation token to stop receiving updates.</param>
public static void StartReceiving(this ITelegratorBot bot, ReceiverOptions? receiverOptions = null, CancellationToken cancellationToken = default)
{
bot.StartReceivingAsync(receiverOptions, cancellationToken)
.ConfigureAwait(false).GetAwaiter().GetResult();
}
}
/// <summary> /// <summary>
/// Provides usefull helper methods for messages /// Provides usefull helper methods for messages
/// </summary> /// </summary>
@@ -412,6 +431,26 @@ public static partial class HandlersCollectionExtensions
"Ocelot", "BouncyCastle", "IdentityModel", "Telegrator" "Ocelot", "BouncyCastle", "IdentityModel", "Telegrator"
]; ];
/// <summary>
/// Collects all handlers from current app domain.
/// Scans for handlers exported by analyzer into class `Telegrator.Analyzers.AnalyzerExport` in each assembly and registers them to the collection.
/// </summary>
/// <param name="handlers"></param>
/// <returns></returns>
public static IHandlersCollection CollectHandlers(this IHandlersCollection handlers)
{
const string exportClassName = "Telegrator.Analyzers.AnalyzerExport";
AppDomain.CurrentDomain.GetAssemblies()
.Select(ass => ass.GetType(exportClassName))
.Squeeze()
.SelectMany(t => t.GetFields())
.Select(f => f.GetValue(null) as Type)
.Squeeze()
.ForEach(v => handlers.AddHandler(v));
return handlers;
}
/// <summary> /// <summary>
/// Collects all public handlers from the current app domain. /// Collects all public handlers from the current app domain.
/// Scans for types that implement handlers and adds them to the collection. /// Scans for types that implement handlers and adds them to the collection.
@@ -438,7 +477,7 @@ public static partial class HandlersCollectionExtensions
{ {
(collectingTarget ?? Assembly.GetCallingAssembly()) (collectingTarget ?? Assembly.GetCallingAssembly())
.GetExportedTypes() .GetExportedTypes()
.Where(type => type.GetCustomAttribute<DontCollectAttribute>() == null && type.IsHandlerRealization()) .Where(type => type.GetCustomAttribute<DontCollectAttribute>() == null && type.IsHandlerImplementation())
.ForEach(type => handlers.AddHandler(type)); .ForEach(type => handlers.AddHandler(type));
return handlers; return handlers;
@@ -496,7 +535,7 @@ public static partial class HandlersCollectionExtensions
/// <exception cref="Exception">Thrown when the type is not a valid handler implementation.</exception> /// <exception cref="Exception">Thrown when the type is not a valid handler implementation.</exception>
public static IHandlersCollection AddHandler(this IHandlersCollection handlers, Type handlerType) public static IHandlersCollection AddHandler(this IHandlersCollection handlers, Type handlerType)
{ {
if (!handlerType.IsHandlerRealization()) if (!handlerType.IsHandlerImplementation())
throw new Exception(); throw new Exception();
if (handlerType.IsCustomDescriptorsProvider()) if (handlerType.IsCustomDescriptorsProvider())
@@ -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("Roslynator", "RCS1037")]
+79
View File
@@ -0,0 +1,79 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Data.Sqlite;
using Microsoft.Extensions.Hosting;
using Telegram.Bot.Polling;
namespace Telegrator.Tests;
internal static class Program
{
public static void HostApplicationBuilder_Example(string[] args)
{
HostApplicationBuilder builder = Host.CreateApplicationBuilder(new HostApplicationBuilderSettings()
{
Args = args,
ApplicationName = "Host example",
});
builder.Services.ConfigureReceiver(new ReceiverOptions()
{
DropPendingUpdates = true,
Limit = 100
});
builder.AddTelegrator(action: builder => builder.Handlers
.CollectHandlersAssemblyWide());
builder.Build()
.UseTelegrator()
.Run();
}
public static void WideBotApplicationBuilder_Example(string[] args)
{
HostApplicationBuilder builder = Host.CreateApplicationBuilder(new HostApplicationBuilderSettings()
{
Args = args,
ApplicationName = "WBot example",
});
builder.Services.ConfigureWideBot(new WideBotOptions()
{
ApiId = 123,
ApiHash = "API_HASH",
DropPendingUpdates = true,
});
builder.AddWideTelegrator(
dbConnectionFactory: provider => new SqliteConnection($"Data Source={Environment.ExpandEnvironmentVariables("%AppData%\\Telegrator\\%wtgb.db")}"),
action: builder => builder.Handlers.CollectHandlersAssemblyWide());
builder.Build()
.UseWideTelegrator()
.Run();
}
public static void WebApplicationBuilder_Example(string[] args)
{
WebApplicationBuilder builder = WebApplication.CreateBuilder(new WebApplicationOptions()
{
Args = args,
ApplicationName = "WebApplication example",
});
builder.Services.ConfigureWebhooker(new WebhookerOptions()
{
WebhookUri = "https://medic-gaming.com/",
DropPendingUpdates = true,
SecretToken = "MEDIC_GAMING"
});
builder.AddTelegratorWeb(action: builder => builder.Handlers
.CollectHandlersAssemblyWide());
builder.Build()
.UseTelegratorWeb(dontMap: true)
.RemapWebhook("https://amazing-butt-sex.cloudpub.ru/")
.Run();
}
}
@@ -9,6 +9,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.7" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.6.6" /> <PackageReference Include="xunit" Version="2.6.6" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.5.6" />
@@ -18,6 +19,10 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\Telegartor.RedisStateStorage\Telegartor.RedisStateStorage.csproj" />
<ProjectReference Include="..\..\src\Telegrator.Hosting.Web\Telegrator.Hosting.Web.csproj" />
<ProjectReference Include="..\..\src\Telegrator.Hosting.WideBot\Telegrator.Hosting.WideBot.csproj" />
<ProjectReference Include="..\..\src\Telegrator.Localized\Telegrator.Localized.csproj" />
<ProjectReference Include="..\..\src\Telegrator\Telegrator.csproj" /> <ProjectReference Include="..\..\src\Telegrator\Telegrator.csproj" />
<ProjectReference Include="..\..\src\Telegrator.Hosting\Telegrator.Hosting.csproj" /> <ProjectReference Include="..\..\src\Telegrator.Hosting\Telegrator.Hosting.csproj" />
</ItemGroup> </ItemGroup>
+8 -10
View File
@@ -1,16 +1,15 @@
using Telegram.Bot.Types; using Telegram.Bot.Types;
using Telegrator.Handlers; using Telegrator.Handlers;
namespace Telegrator.Tests namespace Telegrator.Tests;
/// <summary>
/// Вспомогательный класс для тестирования абстрактного UpdateHandlerBase.
/// ПРИНЦИП: Создание тестовых двойников для абстрактных классов
/// </summary>
[MessageHandler]
internal class TestUpdateHandler : MessageHandler
{ {
/// <summary>
/// Вспомогательный класс для тестирования абстрактного UpdateHandlerBase.
///
/// ПРИНЦИП: Создание тестовых двойников для абстрактных классов
/// </summary>
[MessageHandler]
internal class TestUpdateHandler : MessageHandler
{
public bool WasExecuted { get; private set; } public bool WasExecuted { get; private set; }
public override Task<Result> Execute(IHandlerContainer<Message> container, CancellationToken cancellationToken) public override Task<Result> Execute(IHandlerContainer<Message> container, CancellationToken cancellationToken)
@@ -19,5 +18,4 @@ namespace Telegrator.Tests
WasExecuted = true; WasExecuted = true;
return Task.FromResult(Result.Ok()); return Task.FromResult(Result.Ok());
} }
}
} }