* Little renaming in StateKeeping namespace
* Changed "FilterAnnotation{T}" to work withou type specific sub-classes
* Changed interfaces "IUpdateRouter" and "IHandlersProvider" to match their names more correctly. Before filter validating was on providers, now its router works AS ITS SHOULD BE
This commit is contained in:
@@ -39,39 +39,5 @@ namespace Telegrator.Annotations.StateKeeping
|
||||
/// <param name="myState">The string state to associate</param>
|
||||
public StringStateAttribute(string myState)
|
||||
: base(myState, new SenderIdResolver()) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the attribute with a specific state, a custom key resolver, and a set of possible states.
|
||||
/// </summary>
|
||||
/// <param name="myState">The string state to associate</param>
|
||||
/// <param name="keyResolver">The key resolver for state keeping</param>
|
||||
/// <param name="states">The set of possible string states</param>
|
||||
public StringStateAttribute(string myState, IStateKeyResolver<long> keyResolver, params string[] states)
|
||||
: base(new StringStateKeeper(states), myState, keyResolver) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the attribute with a special state, a custom key resolver, and a set of possible states.
|
||||
/// </summary>
|
||||
/// <param name="specialState">The special state to associate</param>
|
||||
/// <param name="keyResolver">The key resolver for state keeping</param>
|
||||
/// <param name="states">The set of possible string states</param>
|
||||
public StringStateAttribute(SpecialState specialState, IStateKeyResolver<long> keyResolver, params string[] states)
|
||||
: base(new StringStateKeeper(states), specialState, keyResolver) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the attribute with a specific state, the default sender ID resolver, and a set of possible states.
|
||||
/// </summary>
|
||||
/// <param name="myState">The string state to associate</param>
|
||||
/// <param name="states">The set of possible string states</param>
|
||||
public StringStateAttribute(string myState, params string[] states)
|
||||
: base(new StringStateKeeper(states), myState, new SenderIdResolver()) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the attribute with a special state, the default sender ID resolver, and a set of possible states.
|
||||
/// </summary>
|
||||
/// <param name="specialState">The special state to associate</param>
|
||||
/// <param name="states">The set of possible string states</param>
|
||||
public StringStateAttribute(SpecialState specialState, params string[] states)
|
||||
: base(new StringStateKeeper(states), specialState, new SenderIdResolver()) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,10 @@ namespace Telegrator.Attributes
|
||||
public abstract class FilterAnnotation<T> : UpdateFilterAttribute<T>, IFilter<T> where T : class
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool IsCollectible => false;
|
||||
public virtual bool IsCollectible { get; } = false;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override UpdateType[] AllowedTypes { get; } = typeof(T).GetAllowedUpdateTypes();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes new instance of <see cref="FilterAnnotation{T}"/>
|
||||
@@ -23,27 +26,11 @@ namespace Telegrator.Attributes
|
||||
AnonymousFilter = AnonymousTypeFilter.Compile(UpdateFilter, GetFilterringTarget);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override T? GetFilterringTarget(Update update)
|
||||
=> update.GetActualUpdateObject<T>();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public abstract bool CanPass(FilterExecutionContext<T> context);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public abstract class MessageFilterAnnotation() : FilterAnnotation<Message>()
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override UpdateType[] AllowedTypes => [UpdateType.Message, UpdateType.EditedMessage, UpdateType.ChannelPost, UpdateType.EditedChannelPost, UpdateType.BusinessMessage, UpdateType.EditedBusinessMessage];
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Message? GetFilterringTarget(Update update) => update.Message;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public abstract class CallbackQueryFilterAnnotation() : FilterAnnotation<CallbackQuery>()
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override UpdateType[] AllowedTypes => [UpdateType.CallbackQuery];
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override CallbackQuery? GetFilterringTarget(Update update) => update.CallbackQuery;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,10 +15,20 @@ namespace Telegrator.Attributes
|
||||
/// <typeparam name="TKeeper">The type of the state keeper implementation.</typeparam>
|
||||
public abstract class StateKeeperAttribute<TKey, TState, TKeeper> : StateKeeperAttributeBase where TKey : notnull where TState : notnull where TKeeper : StateKeeperBase<TKey, TState>, new()
|
||||
{
|
||||
/*
|
||||
private static readonly TKeeper _shared = new TKeeper();
|
||||
private static readonly Dictionary<TKey, TKeeper> _keyed = [];
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the singleton instance of the state keeper for this attribute type.
|
||||
/// </summary>
|
||||
public static TKeeper StateKeeper { get; internal set; } = null!;
|
||||
public static TKeeper Shared { get; } = new TKeeper();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default state value of this statekeeper.
|
||||
/// </summary>
|
||||
public static TState DefaultState => Shared.DefaultState;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the state value associated with this attribute instance.
|
||||
@@ -37,8 +47,7 @@ namespace Telegrator.Attributes
|
||||
/// <param name="keyResolver">The key resolver for state keeping</param>
|
||||
protected StateKeeperAttribute(TState myState, IStateKeyResolver<TKey> keyResolver) : base(typeof(TKeeper))
|
||||
{
|
||||
StateKeeper ??= new TKeeper();
|
||||
StateKeeper.KeyResolver = keyResolver;
|
||||
Shared.KeyResolver = keyResolver;
|
||||
MyState = myState;
|
||||
SpecialState = SpecialState.None;
|
||||
}
|
||||
@@ -50,12 +59,12 @@ namespace Telegrator.Attributes
|
||||
/// <param name="keyResolver">The key resolver for state keeping</param>
|
||||
protected StateKeeperAttribute(SpecialState specialState, IStateKeyResolver<TKey> keyResolver) : base(typeof(TKeeper))
|
||||
{
|
||||
StateKeeper ??= new TKeeper();
|
||||
StateKeeper.KeyResolver = keyResolver;
|
||||
MyState = StateKeeper.DefaultState;
|
||||
Shared.KeyResolver = keyResolver;
|
||||
MyState = Shared.DefaultState;
|
||||
SpecialState = specialState;
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Initializes the attribute with a custom state keeper, a specific state, and a custom key resolver.
|
||||
/// </summary>
|
||||
@@ -83,6 +92,7 @@ namespace Telegrator.Attributes
|
||||
MyState = StateKeeper.DefaultState;
|
||||
SpecialState = specialState;
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the current update context passes the state filter.
|
||||
@@ -94,7 +104,7 @@ namespace Telegrator.Attributes
|
||||
if (SpecialState == SpecialState.AnyState)
|
||||
return true;
|
||||
|
||||
if (!StateKeeper.TryGetState(context.Input, out TState? state))
|
||||
if (!Shared.TryGetState(context.Input, out TState? state))
|
||||
return SpecialState == SpecialState.NoState;
|
||||
|
||||
if (state == null)
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegrator.Handlers.Components;
|
||||
using Telegrator.MadiatorCore.Descriptors;
|
||||
|
||||
@@ -17,51 +15,22 @@ namespace Telegrator.MadiatorCore
|
||||
public IEnumerable<UpdateType> AllowedTypes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the handlers for the specified update and context.
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="updateRouter">The update router.</param>
|
||||
/// <param name="client">The Telegram bot client.</param>
|
||||
/// <param name="update">The update to handle.</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns>An enumerable of described handler info.</returns>
|
||||
public IEnumerable<DescribedHandlerInfo> GetHandlers(IUpdateRouter updateRouter, ITelegramBotClient client, Update update, CancellationToken cancellationToken = default);
|
||||
/// <param name="updateType"></param>
|
||||
/// <param name="list"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryGetDescriptorList(UpdateType updateType, out HandlerDescriptorList? list);
|
||||
|
||||
/// <summary>
|
||||
/// Describes all handler descriptors in the list for the given context.
|
||||
/// </summary>
|
||||
/// <param name="descriptors">The handler descriptor list.</param>
|
||||
/// <param name="updateRouter">The update router.</param>
|
||||
/// <param name="client">The Telegram bot client.</param>
|
||||
/// <param name="update">The update to handle.</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns>An enumerable of described handler info.</returns>
|
||||
public IEnumerable<DescribedHandlerInfo> DescribeDescriptors(HandlerDescriptorList descriptors, IUpdateRouter updateRouter, ITelegramBotClient client, Update update, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Describes a single handler descriptor for the given context.
|
||||
/// </summary>
|
||||
/// <param name="descriptor">The handler descriptor.</param>
|
||||
/// <param name="updateRouter">The update router.</param>
|
||||
/// <param name="client">The Telegram bot client.</param>
|
||||
/// <param name="update">The update to handle.</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns>The described handler info, or null if not applicable.</returns>
|
||||
public DescribedHandlerInfo? DescribeHandler(HandlerDescriptor descriptor, IUpdateRouter updateRouter, ITelegramBotClient client, Update update, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an instance of the handler for the specified descriptor.
|
||||
/// Instantiates a handler for the given descriptor, using the appropriate creation strategy based on descriptor type.
|
||||
/// Supports singleton, implicit, keyed, and general descriptor types with different instantiation patterns.
|
||||
/// </summary>
|
||||
/// <param name="descriptor">The handler descriptor.</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns>The handler instance.</returns>
|
||||
/// <returns>An instance of <see cref="UpdateHandlerBase"/> for the descriptor</returns>
|
||||
public UpdateHandlerBase GetHandlerInstance(HandlerDescriptor descriptor, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of bot commands supported by the provider.
|
||||
/// </summary>
|
||||
/// <returns>An enumerable of bot commands.</returns>
|
||||
public IEnumerable<BotCommand> GetBotCommands(CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the provider contains any handlers.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Text;
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Polling;
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegrator.Configuration;
|
||||
using Telegrator.Filters.Components;
|
||||
using Telegrator.Handlers.Components;
|
||||
using Telegrator.MadiatorCore;
|
||||
using Telegrator.MadiatorCore.Descriptors;
|
||||
@@ -17,25 +17,11 @@ namespace Telegrator.Polling
|
||||
/// </summary>
|
||||
public class UpdateRouter : IUpdateRouter
|
||||
{
|
||||
/// <summary>
|
||||
/// The bot configuration options.
|
||||
/// </summary>
|
||||
private readonly TelegramBotOptions _options;
|
||||
|
||||
/// <summary>
|
||||
/// The provider for regular handlers.
|
||||
/// </summary>
|
||||
private readonly IHandlersProvider _handlersProvider;
|
||||
|
||||
/// <summary>
|
||||
/// The provider for awaiting handlers.
|
||||
/// </summary>
|
||||
private readonly IAwaitingProvider _awaitingProvider;
|
||||
|
||||
/// <summary>
|
||||
/// The pool for managing handler execution.
|
||||
/// </summary>
|
||||
private readonly IUpdateHandlersPool _HandlersPool;
|
||||
private readonly ITelegramBotInfo _botInfo;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IHandlersProvider HandlersProvider => _handlersProvider;
|
||||
@@ -61,12 +47,14 @@ namespace Telegrator.Polling
|
||||
/// <param name="handlersProvider">The provider for regular handlers.</param>
|
||||
/// <param name="awaitingProvider">The provider for awaiting handlers.</param>
|
||||
/// <param name="options">The bot configuration options.</param>
|
||||
public UpdateRouter(IHandlersProvider handlersProvider, IAwaitingProvider awaitingProvider, TelegramBotOptions options)
|
||||
/// <param name="botInfo"></param>
|
||||
public UpdateRouter(IHandlersProvider handlersProvider, IAwaitingProvider awaitingProvider, TelegramBotOptions options, ITelegramBotInfo botInfo)
|
||||
{
|
||||
_options = options;
|
||||
_handlersProvider = handlersProvider;
|
||||
_awaitingProvider = awaitingProvider;
|
||||
_HandlersPool = new UpdateHandlersPool(_options, _options.GlobalCancellationToken);
|
||||
_botInfo = botInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -76,12 +64,14 @@ namespace Telegrator.Polling
|
||||
/// <param name="awaitingProvider">The provider for awaiting handlers.</param>
|
||||
/// <param name="options">The bot configuration options.</param>
|
||||
/// <param name="handlersPool">The custom handlers pool to use.</param>
|
||||
public UpdateRouter(IHandlersProvider handlersProvider, IAwaitingProvider awaitingProvider, TelegramBotOptions options, IUpdateHandlersPool handlersPool)
|
||||
/// <param name="botInfo"></param>
|
||||
public UpdateRouter(IHandlersProvider handlersProvider, IAwaitingProvider awaitingProvider, TelegramBotOptions options, IUpdateHandlersPool handlersPool, ITelegramBotInfo botInfo)
|
||||
{
|
||||
_options = options;
|
||||
_handlersProvider = handlersProvider;
|
||||
_awaitingProvider = awaitingProvider;
|
||||
_HandlersPool = handlersPool;
|
||||
_botInfo = botInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -112,38 +102,139 @@ namespace Telegrator.Polling
|
||||
LeveledDebug.RouterWriteLine("Received Update ({0}) of type \"{1}\"", update.Id, update.Type);
|
||||
LogUpdate(update);
|
||||
|
||||
// Queuing handlers for execution
|
||||
foreach (DescribedHandlerInfo handler in GetHandlers(botClient, update, cancellationToken))
|
||||
HandlersPool.Enqueue(handler);
|
||||
|
||||
LeveledDebug.RouterWriteLine("Receiving Update ({0}) finished", update.Id);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private IEnumerable<DescribedHandlerInfo> GetHandlers(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Getting handlers in update awaiting pool
|
||||
IEnumerable<DescribedHandlerInfo> handlers = AwaitingProvider.GetHandlers(this, botClient, update, cancellationToken);
|
||||
if (handlers.Any() && Options.ExclusiveAwaitingHandlerRouting)
|
||||
return handlers;
|
||||
IEnumerable<DescribedHandlerInfo> handlers = GetHandlers(AwaitingProvider, this, botClient, update, cancellationToken);
|
||||
if (handlers.Any())
|
||||
{
|
||||
// Enqueuing found awiting handlers
|
||||
HandlersPool.Enqueue(handlers);
|
||||
|
||||
return handlers.Concat(HandlersProvider.GetHandlers(this, botClient, update, cancellationToken));
|
||||
// Chicking if awaiting handlers has exclusive routing
|
||||
if (Options.ExclusiveAwaitingHandlerRouting)
|
||||
{
|
||||
LeveledDebug.RouterWriteLine("Receiving Update ({0}) completed with only awaiting handlers", update.Id);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
// Queuing reagular handlers for execution
|
||||
HandlersPool.Enqueue(GetHandlers(HandlersProvider, this, botClient, update, cancellationToken));
|
||||
LeveledDebug.RouterWriteLine("Receiving Update ({0}) finished", update.Id);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
_ = 0xBAD + 0xC0DE;
|
||||
return [];
|
||||
LeveledDebug.RouterWriteLine("Receiving Update ({0}) cancelled", update.Id);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LeveledDebug.RouterWriteLine("Receiving Update ({0}) finished with exception {1}", update.Id, ex.Message);
|
||||
ExceptionHandler?.HandleException(botClient, ex, HandleErrorSource.PollingError, cancellationToken);
|
||||
return [];
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
private static void LogUpdate(Update update)
|
||||
/// <summary>
|
||||
/// Gets the handlers that match the specified update, using the provided router and client.
|
||||
/// Searches for handlers by update type, falling back to Unknown type if no specific handlers are found.
|
||||
/// </summary>
|
||||
/// <param name="provider">The privode used to get handlers instance</param>
|
||||
/// <param name="updateRouter">The update router for handler execution</param>
|
||||
/// <param name="client">The Telegram bot client instance</param>
|
||||
/// <param name="update">The incoming Telegram update to process</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns>A collection of described handler information for the update</returns>
|
||||
protected virtual IEnumerable<DescribedHandlerInfo> GetHandlers(IHandlersProvider provider, IUpdateRouter updateRouter, ITelegramBotClient client, Update update, CancellationToken cancellationToken = default)
|
||||
{
|
||||
LeveledDebug.ProviderWriteLine("Requested handlers for UpdateType.{0}", update.Type);
|
||||
if (!provider.TryGetDescriptorList(update.Type, out HandlerDescriptorList? descriptors))
|
||||
{
|
||||
LeveledDebug.ProviderWriteLine("No registered, providing Any");
|
||||
provider.TryGetDescriptorList(UpdateType.Unknown, out descriptors);
|
||||
}
|
||||
|
||||
if (descriptors == null || descriptors.Count == 0)
|
||||
{
|
||||
LeveledDebug.ProviderWriteLine("No handlers provided");
|
||||
return [];
|
||||
}
|
||||
|
||||
IEnumerable<DescribedHandlerInfo> described = DescribeDescriptors(provider, descriptors, updateRouter, client, update, cancellationToken);
|
||||
LeveledDebug.ProviderWriteLine("Described total of {0} handlers for Update ({1}) from {2} provider", described.Count(), update.Id, provider.GetType().Name);
|
||||
LeveledDebug.ProviderWriteLine("Described handlers : {0}", string.Join(", ", described));
|
||||
return described;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Describes all handler descriptors for a given update context.
|
||||
/// Processes descriptors in reverse order and respects the ExecuteOnlyFirstFoundHanlder option.
|
||||
/// </summary>
|
||||
/// <param name="provider">The privode used to get handlers instance</param>
|
||||
/// <param name="descriptors">The list of handler descriptors to process</param>
|
||||
/// <param name="updateRouter">The update router for handler execution</param>
|
||||
/// <param name="client">The Telegram bot client instance</param>
|
||||
/// <param name="update">The incoming Telegram update to process</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns>A collection of described handler information</returns>
|
||||
protected virtual IEnumerable<DescribedHandlerInfo> DescribeDescriptors(IHandlersProvider provider, HandlerDescriptorList descriptors, IUpdateRouter updateRouter, ITelegramBotClient client, Update update, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
LeveledDebug.ProviderWriteLine("Describing descriptors of descriptorsList.HandlingType.{0} for Update ({1})", descriptors.HandlingType, update.Id);
|
||||
foreach (HandlerDescriptor descriptor in descriptors.Reverse())
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
DescribedHandlerInfo? describedHandler = DescribeHandler(provider, descriptor, updateRouter, client, update, cancellationToken);
|
||||
if (describedHandler == null)
|
||||
continue;
|
||||
|
||||
yield return describedHandler;
|
||||
if (Options.ExecuteOnlyFirstFoundHanlder)
|
||||
break;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
LeveledDebug.ProviderWriteLine("Describing for Update ({0}) finished", update.Id);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Describes a single handler descriptor for a given update context.
|
||||
/// Validates the handler's filters against the update and creates a handler instance if validation passes.
|
||||
/// </summary>
|
||||
/// <param name="provider">The privode used to get handlers instance</param>
|
||||
/// <param name="descriptor">The handler descriptor to process</param>
|
||||
/// <param name="updateRouter">The update router for handler execution</param>
|
||||
/// <param name="client">The Telegram bot client instance</param>
|
||||
/// <param name="update">The incoming Telegram update to process</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns>The described handler info if validation passes; otherwise, null</returns>
|
||||
public virtual DescribedHandlerInfo? DescribeHandler(IHandlersProvider provider, HandlerDescriptor descriptor, IUpdateRouter updateRouter, ITelegramBotClient client, Update update, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
Dictionary<string, object> data = new Dictionary<string, object>()
|
||||
{
|
||||
{ "handler_name", descriptor.ToString() }
|
||||
};
|
||||
|
||||
FilterExecutionContext<Update> filterContext = new FilterExecutionContext<Update>(_botInfo, update, update, data, []);
|
||||
if (!descriptor.Filters.Validate(filterContext))
|
||||
return null;
|
||||
|
||||
UpdateHandlerBase handlerInstance = provider.GetHandlerInstance(descriptor, cancellationToken);
|
||||
return new DescribedHandlerInfo(updateRouter, client, handlerInstance, filterContext, descriptor.DisplayString);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Methos used to log received <see cref="Update"/> object
|
||||
/// </summary>
|
||||
/// <param name="update"></param>
|
||||
/// <exception cref="NullReferenceException"></exception>
|
||||
protected static void LogUpdate(Update update)
|
||||
{
|
||||
switch (update.Type)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegrator.Configuration;
|
||||
using Telegrator.MadiatorCore;
|
||||
using Telegrator.MadiatorCore.Descriptors;
|
||||
@@ -11,8 +10,7 @@ namespace Telegrator.Providers
|
||||
/// Extends HandlersProvider to provide functionality for creating and managing awaiter handlers.
|
||||
/// </summary>
|
||||
/// <param name="options">The bot configuration options.</param>
|
||||
/// <param name="botInfo">The bot information.</param>
|
||||
public class AwaitingProvider(TelegramBotOptions options, ITelegramBotInfo botInfo) : HandlersProvider([], options, botInfo), IAwaitingProvider
|
||||
public class AwaitingProvider(TelegramBotOptions options) : HandlersProvider([], options), IAwaitingProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// List of handler descriptors for awaiting handlers.
|
||||
@@ -20,9 +18,10 @@ namespace Telegrator.Providers
|
||||
protected readonly HandlerDescriptorList HandlersList = [];
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override IEnumerable<DescribedHandlerInfo> GetHandlers(IUpdateRouter updateRouter, ITelegramBotClient client, Update update, CancellationToken cancellationToken = default)
|
||||
public override bool TryGetDescriptorList(UpdateType updateType, out HandlerDescriptorList? list)
|
||||
{
|
||||
return DescribeDescriptors(HandlersList, updateRouter, client, update, cancellationToken);
|
||||
list = HandlersList;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegrator.Annotations;
|
||||
using Telegrator.Configuration;
|
||||
using Telegrator.Filters.Components;
|
||||
using Telegrator.Handlers.Components;
|
||||
using Telegrator.MadiatorCore;
|
||||
using Telegrator.MadiatorCore.Descriptors;
|
||||
@@ -27,31 +22,24 @@ namespace Telegrator.Providers
|
||||
/// Read-only dictionary mapping <see cref="UpdateType"/> to lists of handler descriptors.
|
||||
/// Each descriptor list is frozen to prevent modification after initialization.
|
||||
/// </summary>
|
||||
protected readonly ReadOnlyDictionary<UpdateType, HandlerDescriptorList> HandlersDictionary;
|
||||
public readonly ReadOnlyDictionary<UpdateType, HandlerDescriptorList> HandlersDictionary;
|
||||
|
||||
/// <summary>
|
||||
/// Configuration options for the bot and handler execution behavior.
|
||||
/// </summary>
|
||||
protected readonly TelegramBotOptions Options;
|
||||
|
||||
/// <summary>
|
||||
/// Information about the Telegram bot instance, used for filter context creation.
|
||||
/// </summary>
|
||||
protected readonly ITelegramBotInfo BotInfo;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="HandlersProvider"/> with the specified handler collections and configuration.
|
||||
/// </summary>
|
||||
/// <param name="handlers">Collection of handler descriptor lists organized by update type</param>
|
||||
/// <param name="options">Configuration options for the bot and handler execution</param>
|
||||
/// <param name="botInfo">Information about the Telegram bot instance</param>
|
||||
/// <exception cref="ArgumentNullException">Thrown when options or botInfo is null</exception>
|
||||
public HandlersProvider(IHandlersCollection handlers, TelegramBotOptions options, ITelegramBotInfo botInfo)
|
||||
public HandlersProvider(IHandlersCollection handlers, TelegramBotOptions options)
|
||||
{
|
||||
AllowedTypes = handlers.AllowedTypes;
|
||||
HandlersDictionary = handlers.Values.ForEach(list => list.Freeze()).ToReadOnlyDictionary(list => list.HandlingType);
|
||||
Options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
BotInfo = botInfo ?? throw new ArgumentNullException(nameof(botInfo));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -59,112 +47,15 @@ namespace Telegrator.Providers
|
||||
/// </summary>
|
||||
/// <param name="handlers">Collection of handler descriptor lists organized by update type</param>
|
||||
/// <param name="options">Configuration options for the bot and handler execution</param>
|
||||
/// <param name="botInfo">Information about the Telegram bot instance</param>
|
||||
/// <exception cref="ArgumentNullException">Thrown when options or botInfo is null</exception>
|
||||
public HandlersProvider(IEnumerable<HandlerDescriptorList> handlers, TelegramBotOptions options, ITelegramBotInfo botInfo)
|
||||
public HandlersProvider(IEnumerable<HandlerDescriptorList> handlers, TelegramBotOptions options)
|
||||
{
|
||||
AllowedTypes = Update.AllTypes;
|
||||
HandlersDictionary = handlers.ForEach(list => list.Freeze()).ToReadOnlyDictionary(list => list.HandlingType);
|
||||
Options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
BotInfo = botInfo ?? throw new ArgumentNullException(nameof(botInfo));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the handlers that match the specified update, using the provided router and client.
|
||||
/// Searches for handlers by update type, falling back to Unknown type if no specific handlers are found.
|
||||
/// </summary>
|
||||
/// <param name="updateRouter">The update router for handler execution</param>
|
||||
/// <param name="client">The Telegram bot client instance</param>
|
||||
/// <param name="update">The incoming Telegram update to process</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns>A collection of described handler information for the update</returns>
|
||||
public virtual IEnumerable<DescribedHandlerInfo> GetHandlers(IUpdateRouter updateRouter, ITelegramBotClient client, Update update, CancellationToken cancellationToken = default)
|
||||
{
|
||||
LeveledDebug.ProviderWriteLine("Requested handlers for UpdateType.{0}", update.Type);
|
||||
if (!HandlersDictionary.TryGetValue(update.Type, out HandlerDescriptorList? descriptors))
|
||||
{
|
||||
LeveledDebug.ProviderWriteLine("No registered, providing Any");
|
||||
HandlersDictionary.TryGetValue(UpdateType.Unknown, out descriptors);
|
||||
}
|
||||
|
||||
if (descriptors == null || descriptors.Count == 0)
|
||||
{
|
||||
LeveledDebug.ProviderWriteLine("No handlers provided");
|
||||
return [];
|
||||
}
|
||||
|
||||
IEnumerable<DescribedHandlerInfo> described = DescribeDescriptors(descriptors, updateRouter, client, update, cancellationToken);
|
||||
LeveledDebug.ProviderWriteLine("Described total of {0} handlers for Update ({1})", described.Count(), update.Id);
|
||||
LeveledDebug.ProviderWriteLine("Described handlers : {0}", string.Join(", ", described));
|
||||
return described;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Describes all handler descriptors for a given update context.
|
||||
/// Processes descriptors in reverse order and respects the ExecuteOnlyFirstFoundHanlder option.
|
||||
/// </summary>
|
||||
/// <param name="descriptors">The list of handler descriptors to process</param>
|
||||
/// <param name="updateRouter">The update router for handler execution</param>
|
||||
/// <param name="client">The Telegram bot client instance</param>
|
||||
/// <param name="update">The incoming Telegram update to process</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns>A collection of described handler information</returns>
|
||||
public virtual IEnumerable<DescribedHandlerInfo> DescribeDescriptors(HandlerDescriptorList descriptors, IUpdateRouter updateRouter, ITelegramBotClient client, Update update, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
LeveledDebug.ProviderWriteLine("Describing descriptors of descriptorsList.HandlingType.{0} for Update ({1})", descriptors.HandlingType, update.Id);
|
||||
foreach (HandlerDescriptor descriptor in descriptors.Reverse())
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
DescribedHandlerInfo? describedHandler = DescribeHandler(descriptor, updateRouter, client, update, cancellationToken);
|
||||
if (describedHandler == null)
|
||||
continue;
|
||||
|
||||
yield return describedHandler;
|
||||
if (Options.ExecuteOnlyFirstFoundHanlder)
|
||||
break;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
LeveledDebug.ProviderWriteLine("Describing for Update ({0}) finished", update.Id);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Describes a single handler descriptor for a given update context.
|
||||
/// Validates the handler's filters against the update and creates a handler instance if validation passes.
|
||||
/// </summary>
|
||||
/// <param name="descriptor">The handler descriptor to process</param>
|
||||
/// <param name="updateRouter">The update router for handler execution</param>
|
||||
/// <param name="client">The Telegram bot client instance</param>
|
||||
/// <param name="update">The incoming Telegram update to process</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns>The described handler info if validation passes; otherwise, null</returns>
|
||||
public virtual DescribedHandlerInfo? DescribeHandler(HandlerDescriptor descriptor, IUpdateRouter updateRouter, ITelegramBotClient client, Update update, CancellationToken cancellationToken = default)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
Dictionary<string, object> data = new Dictionary<string, object>()
|
||||
{
|
||||
{ "handler_name", descriptor.ToString() }
|
||||
};
|
||||
|
||||
FilterExecutionContext<Update> filterContext = new FilterExecutionContext<Update>(BotInfo, update, update, data, []);
|
||||
if (!descriptor.Filters.Validate(filterContext))
|
||||
return null;
|
||||
|
||||
UpdateHandlerBase handlerInstance = GetHandlerInstance(descriptor, cancellationToken);
|
||||
return new DescribedHandlerInfo(updateRouter, client, handlerInstance, filterContext, descriptor.DisplayString);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a handler for the given descriptor, using the appropriate creation strategy based on descriptor type.
|
||||
/// Supports singleton, implicit, keyed, and general descriptor types with different instantiation patterns.
|
||||
/// </summary>
|
||||
/// <param name="descriptor">The handler descriptor containing type and instantiation information</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns>An instance of <see cref="UpdateHandlerBase"/> for the descriptor</returns>
|
||||
/// <inheritdoc/>
|
||||
/// <exception cref="Exception">Thrown when the descriptor type is not recognized</exception>
|
||||
public virtual UpdateHandlerBase GetHandlerInstance(HandlerDescriptor descriptor, CancellationToken cancellationToken = default)
|
||||
{
|
||||
@@ -192,31 +83,13 @@ namespace Telegrator.Providers
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of bot commands defined by all handler types with <see cref="CommandAlliasAttribute"/>.
|
||||
/// Extracts command aliases and descriptions from message handlers for bot command registration.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns>A collection of <see cref="BotCommand"/> objects for the bot</returns>
|
||||
public IEnumerable<BotCommand> GetBotCommands(CancellationToken cancellationToken = default)
|
||||
/// <inheritdoc/>
|
||||
public virtual bool TryGetDescriptorList(UpdateType updateType, out HandlerDescriptorList? list)
|
||||
{
|
||||
if (!HandlersDictionary.TryGetValue(UpdateType.Message, out HandlerDescriptorList? list))
|
||||
yield break;
|
||||
|
||||
foreach (BotCommand botCommand in list
|
||||
.Select(descriptor => descriptor.HandlerType)
|
||||
.SelectMany(handlerType => handlerType.GetCustomAttributes<CommandAlliasAttribute>()
|
||||
.SelectMany(attribute => attribute.Alliases.Select(alias => new BotCommand(alias, attribute.Description)))))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
yield return botCommand;
|
||||
}
|
||||
return HandlersDictionary.TryGetValue(updateType, out list);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the provider contains any handlers.
|
||||
/// </summary>
|
||||
/// <returns>True if there are no handlers registered; otherwise, false</returns>
|
||||
/// <inheritdoc/>
|
||||
public virtual bool IsEmpty()
|
||||
{
|
||||
return HandlersDictionary.Count == 0;
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Telegrator.StateKeeping
|
||||
/// <param name="_">The handler container (unused parameter for extension method syntax).</param>
|
||||
/// <returns>The enum state keeper instance.</returns>
|
||||
public static EnumStateKeeper<TEnum> EnumStateKeeper<TEnum>(this IHandlerContainer _) where TEnum : Enum
|
||||
=> EnumStateAttribute<TEnum>.StateKeeper;
|
||||
=> EnumStateAttribute<TEnum>.Shared;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new enum state for the current update.
|
||||
@@ -55,7 +55,7 @@ namespace Telegrator.StateKeeping
|
||||
/// <param name="container">The handler container.</param>
|
||||
/// <param name="newState">The new state value. If null, uses the default state.</param>
|
||||
public static void SetEnumState<TEnum>(this IHandlerContainer container, TEnum? newState) where TEnum : Enum
|
||||
=> container.EnumStateKeeper<TEnum>().SetState(container.HandlingUpdate, newState ?? EnumStateAttribute<TEnum>.StateKeeper.DefaultState);
|
||||
=> container.EnumStateKeeper<TEnum>().SetState(container.HandlingUpdate, newState ?? EnumStateAttribute<TEnum>.DefaultState);
|
||||
|
||||
/// <summary>
|
||||
/// Moves the enum state forward to the next value in the enum sequence.
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Telegrator.StateKeeping
|
||||
/// <param name="_">The handler container instance</param>
|
||||
/// <returns>The <see cref="NumericStateKeeper"/> instance</returns>
|
||||
public static NumericStateKeeper NumericStateKeeper(this IHandlerContainer _)
|
||||
=> NumericStateAttribute.StateKeeper;
|
||||
=> NumericStateAttribute.Shared;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new numeric state for the current update being handled.
|
||||
@@ -73,7 +73,7 @@ namespace Telegrator.StateKeeping
|
||||
/// <param name="container">The handler container instance</param>
|
||||
/// <param name="newState">The new numeric state to set, or null to use default</param>
|
||||
public static void SetNumericState(this IHandlerContainer container, int? newState)
|
||||
=> container.NumericStateKeeper().SetState(container.HandlingUpdate, newState ?? NumericStateAttribute.StateKeeper.DefaultState);
|
||||
=> container.NumericStateKeeper().SetState(container.HandlingUpdate, newState ?? NumericStateAttribute.DefaultState);
|
||||
|
||||
/// <summary>
|
||||
/// Moves the numeric state forward by incrementing the current value.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Telegrator.Annotations.StateKeeping;
|
||||
using Telegrator.Handlers.Components;
|
||||
using Telegrator.StateKeeping;
|
||||
|
||||
namespace Telegrator.StateKeeping
|
||||
{
|
||||
@@ -34,7 +33,7 @@ namespace Telegrator.StateKeeping
|
||||
/// <param name="_">The handler container instance</param>
|
||||
/// <returns>The <see cref="StringStateKeeper"/> instance</returns>
|
||||
public static StringStateKeeper StringStateKeeper(this IHandlerContainer _)
|
||||
=> StringStateAttribute.StateKeeper;
|
||||
=> StringStateAttribute.Shared;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new string state for the current update being handled.
|
||||
@@ -57,7 +56,7 @@ namespace Telegrator.StateKeeping
|
||||
/// <param name="container">The handler container instance</param>
|
||||
/// <param name="newState">The new string state to set, or null to use default</param>
|
||||
public static void SetStringState(this IHandlerContainer container, string? newState)
|
||||
=> container.StringStateKeeper().SetState(container.HandlingUpdate, newState ?? StringStateAttribute.StateKeeper.DefaultState);
|
||||
=> container.StringStateKeeper().SetState(container.HandlingUpdate, newState ?? StringStateAttribute.DefaultState);
|
||||
|
||||
/// <summary>
|
||||
/// Moves the string state forward to the next state in the sequence.
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<EnableNETAnalyzers>True</EnableNETAnalyzers>
|
||||
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<Version>1.0.2</Version>
|
||||
<Version>1.0.3</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -63,10 +63,10 @@ namespace Telegrator
|
||||
if (Options.GlobalCancellationToken == CancellationToken.None)
|
||||
Options.GlobalCancellationToken = cancellationToken;
|
||||
|
||||
HandlersProvider handlerProvider = new HandlersProvider(Handlers, Options, BotInfo);
|
||||
AwaitingProvider awaitingProvider = new AwaitingProvider(Options, BotInfo);
|
||||
HandlersProvider handlerProvider = new HandlersProvider(Handlers, Options);
|
||||
AwaitingProvider awaitingProvider = new AwaitingProvider(Options);
|
||||
|
||||
updateRouter = new UpdateRouter(handlerProvider, awaitingProvider, Options);
|
||||
updateRouter = new UpdateRouter(handlerProvider, awaitingProvider, Options, BotInfo);
|
||||
StartReceivingInternal(receiverOptions, cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Reflection;
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegram.Bot.Types.Payments;
|
||||
using Telegrator.Annotations;
|
||||
using Telegrator.Annotations.StateKeeping;
|
||||
using Telegrator.Attributes;
|
||||
using Telegrator.Filters.Components;
|
||||
@@ -11,6 +12,7 @@ using Telegrator.Handlers.Building;
|
||||
using Telegrator.Handlers.Building.Components;
|
||||
using Telegrator.Handlers.Components;
|
||||
using Telegrator.MadiatorCore;
|
||||
using Telegrator.MadiatorCore.Descriptors;
|
||||
using Telegrator.Providers;
|
||||
using Telegrator.StateKeeping;
|
||||
using Telegrator.StateKeeping.Components;
|
||||
@@ -87,7 +89,7 @@ namespace Telegrator
|
||||
/// <param name="_">The handler container (unused).</param>
|
||||
/// <returns>The state keeper instance.</returns>
|
||||
public static TKeeper GetStateKeeper<TKey, TState, TKeeper>(this IHandlerContainer _) where TKey : notnull where TState : IEquatable<TState> where TKeeper : StateKeeperBase<TKey, TState>, new()
|
||||
=> StateKeeperAttribute<TKey, TState, TKeeper>.StateKeeper;
|
||||
=> StateKeeperAttribute<TKey, TState, TKeeper>.Shared;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -161,6 +163,31 @@ namespace Telegrator
|
||||
=> awaitingProvider.CreateAbstract<CallbackQuery>(UpdateType.CallbackQuery, handlingUpdate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extesions method for handlers providers
|
||||
/// </summary>
|
||||
public static class HandlersProviderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the list of bot commands supported by the provider.
|
||||
/// </summary>
|
||||
/// <returns>An enumerable of bot commands.</returns>
|
||||
public static IEnumerable<BotCommand> GetBotCommands(this IHandlersProvider provider, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (!provider.TryGetDescriptorList(UpdateType.Message, out HandlerDescriptorList? list))
|
||||
yield break;
|
||||
|
||||
foreach (BotCommand botCommand in list
|
||||
.Select(descriptor => descriptor.HandlerType)
|
||||
.SelectMany(handlerType => handlerType.GetCustomAttributes<CommandAlliasAttribute>()
|
||||
.SelectMany(attribute => attribute.Alliases.Select(alias => new BotCommand(alias, attribute.Description)))))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
yield return botCommand;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for handlers collections.
|
||||
/// Provides convenient methods for creating implicit handlers.
|
||||
@@ -850,6 +877,41 @@ namespace Telegrator
|
||||
_ => update
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Selecting corresponding <see cref="UpdateType"/>s for <see cref="Update"/>'s sub-type
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static UpdateType[] GetAllowedUpdateTypes(this Type type) => type.FullName switch
|
||||
{
|
||||
"Telegram.Bot.Types.Message" => UpdateTypeExtensions.MessageTypes,
|
||||
"Telegram.Bot.Types.ChatMemberUpdated" => [UpdateType.MyChatMember, UpdateType.ChatMember],
|
||||
"Telegram.Bot.Types.InlineQuery" => [UpdateType.InlineQuery],
|
||||
"Telegram.Bot.Types.ChosenInlineResult" => [UpdateType.ChosenInlineResult],
|
||||
"Telegram.Bot.Types.CallbackQuery" => [UpdateType.CallbackQuery],
|
||||
"Telegram.Bot.Types.ShippingQuery" => [UpdateType.ShippingQuery],
|
||||
"Telegram.Bot.Types.PreCheckoutQuery" => [UpdateType.PreCheckoutQuery],
|
||||
"Telegram.Bot.Types.Poll" => [UpdateType.Poll],
|
||||
"Telegram.Bot.Types.PollAnswer" => [UpdateType.PollAnswer],
|
||||
"Telegram.Bot.Types.ChatJoinRequest" => [UpdateType.ChatJoinRequest],
|
||||
"Telegram.Bot.Types.MessageReactionUpdated" => [UpdateType.MessageReaction],
|
||||
"Telegram.Bot.TypesMessageReactionCountUpdated" => [UpdateType.MessageReactionCount],
|
||||
"Telegram.Bot.Types.ChatBoostUpdated" => [UpdateType.ChatBoost],
|
||||
"Telegram.Bot.Types.ChatBoostRemoved" => [UpdateType.RemovedChatBoost],
|
||||
"Telegram.Bot.Types.BusinessConnection" => [UpdateType.BusinessConnection],
|
||||
"Telegram.Bot.Types.BusinessMessagesDeleted" => [UpdateType.DeletedBusinessMessages],
|
||||
"Telegram.Bot.Types.PaidMediaPurchased" => [UpdateType.PurchasedPaidMedia],
|
||||
"Telegram.Bot.Types.Update" => Update.AllTypes,
|
||||
_ => []
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Selecting corresponding <see cref="UpdateType"/>s for <see cref="Update"/>'s sub-type
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static UpdateType[] GetAllowedUpdateTypes<T>() where T : class
|
||||
=> GetAllowedUpdateTypes(typeof(T));
|
||||
|
||||
/// <summary>
|
||||
/// Selects from <see cref="Update"/> an <typeparamref name="T"/> that contains information about the update
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user