* Fixed Result behaviour

* Added AsWClient
* Updated examples
This commit is contained in:
gutii
2026-04-27 21:07:02 +04:00
parent 0e0a280308
commit 5433a2de0d
10 changed files with 149 additions and 79 deletions
+1 -1
View File
@@ -19,7 +19,7 @@
Replaces TelegramBotHostBuilder. Configures DI, options, and handlers. Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
</summary> </summary>
</member> </member>
<member name="M:Telegrator.WideHostBuilderExtensions.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.WideHostBuilderExtensions.AddWideTelegratorInternal(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>
+6 -1
View File
@@ -6377,11 +6377,16 @@
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.InterruptRouter"> <member name="P:Telegrator.Result.Success">
<summary> <summary>
Tell router to stop describing Tell router to stop describing
</summary> </summary>
</member> </member>
<member name="P:Telegrator.Result.RouteNext">
<summary>
Tell router to continue describing
</summary>
</member>
<member name="P:Telegrator.Result.NextType"> <member name="P:Telegrator.Result.NextType">
<summary> <summary>
Exact type that router should search Exact type that router should search
@@ -4,12 +4,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net.Http;
using System.Threading;
using Telegram.Bot; using Telegram.Bot;
using Telegram.Bot.Types; using Telegram.Bot.Types;
using Telegrator.Core; using Telegrator.Core;
@@ -58,6 +53,12 @@ public static class HandlersExtensions
} }
} }
public static WTelegramBotClient AsWClient(this ITelegramBotClient client)
{
return client as WTelegramBotClient
?? throw new InvalidCastException("Client is not assignable to `WTelegram.Bot.WTelegramBotClient`");
}
public static WUpdate AsWUpdate(this Update update) public static WUpdate AsWUpdate(this Update update)
{ {
return update as WUpdate return update as WUpdate
@@ -75,7 +76,7 @@ public static class WideHostBuilderExtensions
/// </summary> /// </summary>
public static IHostApplicationBuilder AddWideTelegrator(this IHostApplicationBuilder builder, TelegratorOptions? options = null, IHandlersCollection? handlers = null, Action<ITelegramBotHostBuilder>? action = null) public static IHostApplicationBuilder AddWideTelegrator(this IHostApplicationBuilder builder, TelegratorOptions? options = null, IHandlersCollection? handlers = null, Action<ITelegramBotHostBuilder>? action = null)
{ {
AddTelegratorInternal(builder.Services, builder.Configuration, builder.Properties, ref handlers, options); AddWideTelegratorInternal(builder.Services, builder.Configuration, builder.Properties, ref handlers, options);
action?.Invoke(new TelegramBotHostBuilder(builder, handlers)); action?.Invoke(new TelegramBotHostBuilder(builder, handlers));
return builder; return builder;
} }
@@ -85,14 +86,14 @@ public static class WideHostBuilderExtensions
/// </summary> /// </summary>
public static IHostApplicationBuilder AddWideTelegrator(this IHostApplicationBuilder builder, TelegratorOptions? options = null, IHandlersCollection? handlers = null) public static IHostApplicationBuilder AddWideTelegrator(this IHostApplicationBuilder builder, TelegratorOptions? options = null, IHandlersCollection? handlers = null)
{ {
AddTelegratorInternal(builder.Services, builder.Configuration, builder.Properties, ref handlers, options); AddWideTelegratorInternal(builder.Services, builder.Configuration, builder.Properties, ref handlers, options);
return builder; return builder;
} }
/// <summary> /// <summary>
/// Replaces TelegramBotHostBuilder. Configures DI, options, and handlers. /// Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
/// </summary> /// </summary>
internal static void AddTelegratorInternal(IServiceCollection services, IConfiguration configuration, IDictionary<object, object> properties, [NotNull] ref IHandlersCollection? handlers, TelegratorOptions? options = null) internal static void AddWideTelegratorInternal(IServiceCollection services, IConfiguration configuration, IDictionary<object, object> properties, [NotNull] ref IHandlersCollection? handlers, TelegratorOptions? options = null)
{ {
if (services.Any(srvc => srvc.ServiceType == typeof(HostedUpdateReceiver))) if (services.Any(srvc => srvc.ServiceType == typeof(HostedUpdateReceiver)))
throw new InvalidOperationException("`HostedUpdateReceiver` found in services. WideHost extension is not compatible with long-polling receiving. Please, remove `AddTelegrator` invocation from your WebApp configuration."); throw new InvalidOperationException("`HostedUpdateReceiver` found in services. WideHost extension is not compatible with long-polling receiving. Please, remove `AddTelegrator` invocation from your WebApp configuration.");
@@ -123,7 +124,7 @@ public static class WideHostBuilderExtensions
services.AddSingleton(handlers); services.AddSingleton(handlers);
properties.Add(HostBuilderExtensions.HandlersCollectionPropertyKey, handlers); properties.Add(HostBuilderExtensions.HandlersCollectionPropertyKey, handlers);
if (!services.Any(srvc => srvc.ImplementationType == typeof(IOptions<WTelegramBotClientOptions>))) if (!services.Any(srvc => srvc.ServiceType == typeof(IOptions<WTelegramBotClientOptions>)))
{ {
// For now, there's no way to configure this from IConfiguration, use `ConfigureWideTelegram` instead // For now, there's no way to configure this from IConfiguration, use `ConfigureWideTelegram` instead
throw new MissingMemberException("No options of type 'WTelegramBotClientOptions' was registered. This configuration is runtime required! Use `ConfigureWideTelegram` to register options."); throw new MissingMemberException("No options of type 'WTelegramBotClientOptions' was registered. This configuration is runtime required! Use `ConfigureWideTelegram` to register options.");
@@ -163,7 +164,13 @@ public static class WideBotServiceCollectionExtensions
} }
private static WTelegramBotClient TypedTelegramBotClientFactory(HttpClient httpClient, IServiceProvider provider) private static WTelegramBotClient TypedTelegramBotClientFactory(HttpClient httpClient, IServiceProvider provider)
=> new WTelegramBotClient(provider.GetRequiredService<IOptions<WTelegramBotClientOptions>>().Value, httpClient); {
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;
}
} }
/// <summary> /// <summary>
@@ -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.InterruptRouter) 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.InterruptRouter) 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.InterruptRouter) 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/>
+12 -14
View File
@@ -97,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);
@@ -111,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.InterruptRouter) 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);
@@ -127,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);
@@ -141,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.InterruptRouter) 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);
@@ -244,13 +238,17 @@ public class UpdateRouter : IUpdateRouter
FiltersFallbackReport report = new FiltersFallbackReport(descriptor, filterContext); FiltersFallbackReport report = new FiltersFallbackReport(descriptor, filterContext);
Result filtersResult = descriptor.Filters.Validate(filterContext, descriptor.FormReport, ref report); Result filtersResult = descriptor.Filters.Validate(filterContext, descriptor.FormReport, ref report);
if (filtersResult.InterruptRouter) if (filtersResult.RouteNext)
return null; {
Result fallbackResult = handlerInstance.FiltersFallback(report, client, cancellationToken).Result; Result fallbackResult = handlerInstance.FiltersFallback(report, client, cancellationToken).Result;
breakRouting = fallbackResult.InterruptRouter; breakRouting = !fallbackResult.RouteNext;
return null; return null;
} }
else if (!filtersResult.Success)
{
return null;
}
}
return new DescribedHandlerDescriptor(descriptor, this, AwaitingProvider, StateStorage, client, handlerInstance, filterContext, descriptor.DisplayString); return new DescribedHandlerDescriptor(descriptor, this, AwaitingProvider, StateStorage, client, handlerInstance, filterContext, descriptor.DisplayString);
} }
+13 -7
View File
@@ -10,23 +10,29 @@ namespace Telegrator;
/// </summary> /// </summary>
public sealed class Result public sealed class Result
{ {
private static readonly Result ok = new Result(true, null); private static readonly Result ok = new Result(true, false, null);
private static readonly Result fault = new Result(true, null); private static readonly Result fault = new Result(false, false, null);
private static readonly Result next = new Result(false, null); private static readonly Result next = new Result(true, true, null);
/// <summary> /// <summary>
/// Tell router to stop describing /// Tell router to stop describing
/// </summary> /// </summary>
public bool InterruptRouter { get; } public bool Success { get; }
/// <summary>
/// Tell router to continue describing
/// </summary>
public bool RouteNext { get; }
/// <summary> /// <summary>
/// Exact type that router should search /// Exact type that router should search
/// </summary> /// </summary>
public Type? NextType { get; } public Type? NextType { get; }
internal Result(bool interruptRouter, Type? nextType) internal Result(bool success, bool routeNext, Type? nextType)
{ {
InterruptRouter = interruptRouter; Success = success;
RouteNext = routeNext;
NextType = nextType; NextType = nextType;
} }
@@ -73,5 +79,5 @@ public sealed class Result
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <returns></returns> /// <returns></returns>
public static Result Next<T>() public static Result Next<T>()
=> new Result(false, typeof(T)); => new Result(true, true, typeof(T));
} }
+1 -1
View File
@@ -32,7 +32,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>
+21 -19
View File
@@ -2,28 +2,12 @@
using Microsoft.Data.Sqlite; using Microsoft.Data.Sqlite;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using System.Data.Common; using System.Data.Common;
using Telegram.Bot;
namespace Telegrator; namespace Telegrator.Tests;
internal static class Program internal static class Program
{ {
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://amazing-butt-sex.cloudpub.ru/")
.Run();
}
public static void HostApplicationBuilder_Example(string[] args) public static void HostApplicationBuilder_Example(string[] args)
{ {
HostApplicationBuilder builder = Host.CreateApplicationBuilder(new HostApplicationBuilderSettings() HostApplicationBuilder builder = Host.CreateApplicationBuilder(new HostApplicationBuilderSettings()
@@ -49,7 +33,8 @@ internal static class Program
}); });
using DbConnection connection = new SqliteConnection(@"Data Source=wtgb.db"); using DbConnection connection = new SqliteConnection(@"Data Source=wtgb.db");
builder.Services.ConfigureWideTelegram(new Telegram.Bot.WTelegramBotClientOptions(token: "BOT_TOKEN", apiId: 123, apiHash: "API_HASH", dbConnection: connection)); builder.Services.ConfigureWideTelegram(
new WTelegramBotClientOptions(token: "BOT_TOKEN", apiId: 123, apiHash: "API_HASH", dbConnection: connection));
builder.AddWideTelegrator(action: builder => builder.Handlers builder.AddWideTelegrator(action: builder => builder.Handlers
.CollectHandlersAssemblyWide()); .CollectHandlersAssemblyWide());
@@ -58,4 +43,21 @@ internal static class Program
.UseWideTelegrator() .UseWideTelegrator()
.Run(); .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://amazing-butt-sex.cloudpub.ru/")
.Run();
}
} }