Добавьте файлы проекта.
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Types;
|
||||
using Telegrator.Filters.Components;
|
||||
using Telegrator.Handlers.Components;
|
||||
using Telegrator.MadiatorCore;
|
||||
using Telegrator.MadiatorCore.Descriptors;
|
||||
|
||||
namespace Telegrator.Handlers
|
||||
{
|
||||
/// <summary>
|
||||
/// Container class that holds the context and data for handler execution.
|
||||
/// Provides access to the update, client, filters, and other execution context.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUpdate">The type of update being handled.</typeparam>
|
||||
public class AbstractHandlerContainer<TUpdate> : IAbstractHandlerContainer<TUpdate> where TUpdate : class
|
||||
{
|
||||
private readonly TUpdate _actualUpdate;
|
||||
private readonly Update _handlingUpdate;
|
||||
private readonly ITelegramBotClient _client;
|
||||
private readonly Dictionary<string, object> _extraData;
|
||||
private readonly CompletedFiltersList _completedFilters;
|
||||
private readonly IAwaitingProvider _awaitingProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the actual update object of type TUpdate.
|
||||
/// </summary>
|
||||
public TUpdate ActualUpdate => _actualUpdate;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Update HandlingUpdate => _handlingUpdate;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ITelegramBotClient Client => _client;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<string, object> ExtraData => _extraData;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public CompletedFiltersList CompletedFilters => _completedFilters;
|
||||
|
||||
/// <inheritdoc cref="IHandlerContainer.AwaitingProvider"/>
|
||||
public IAwaitingProvider AwaitingProvider => _awaitingProvider;
|
||||
|
||||
/// <inheritdoc/>
|
||||
IAwaitingProvider IHandlerContainer.AwaitingProvider => AwaitingProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AbstractHandlerContainer{TUpdate}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="awaitingProvider">The awaiting provider for managing async operations.</param>
|
||||
/// <param name="handlerInfo">The handler information containing execution context.</param>
|
||||
public AbstractHandlerContainer(IAwaitingProvider awaitingProvider, DescribedHandlerInfo handlerInfo)
|
||||
{
|
||||
_actualUpdate = handlerInfo.HandlingUpdate.GetActualUpdateObject<TUpdate>();
|
||||
_handlingUpdate = handlerInfo.HandlingUpdate;
|
||||
_client = handlerInfo.Client;
|
||||
_extraData = handlerInfo.ExtraData;
|
||||
_completedFilters = handlerInfo.CompletedFilters;
|
||||
_awaitingProvider = awaitingProvider;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegrator.Attributes;
|
||||
using Telegrator.Filters.Components;
|
||||
using Telegrator.Handlers.Components;
|
||||
|
||||
namespace Telegrator.Handlers
|
||||
{
|
||||
/// <summary>
|
||||
/// Attribute that marks a handler to process any type of update.
|
||||
/// This handler will be triggered for all incoming updates regardless of their type.
|
||||
/// </summary>
|
||||
/// <param name="concurrency">The maximum number of concurrent executions allowed (default: -1 for unlimited).</param>
|
||||
public class AnyUpdateHandlerAttribute(int concurrency = -1) : UpdateHandlerAttribute<AnyUpdateHandler>(UpdateType.Unknown, concurrency)
|
||||
{
|
||||
/// <summary>
|
||||
/// Always returns true, allowing any update to pass through this filter.
|
||||
/// </summary>
|
||||
/// <param name="context">The filter execution context (unused).</param>
|
||||
/// <returns>Always returns true to allow any update.</returns>
|
||||
public override bool CanPass(FilterExecutionContext<Update> context) => true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract base class for handlers that can process any type of update.
|
||||
/// Provides a foundation for creating handlers that respond to all incoming updates.
|
||||
/// </summary>
|
||||
public abstract class AnyUpdateHandler() : AbstractUpdateHandler<Update>(UpdateType.Unknown)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegrator.Handlers.Components;
|
||||
using Telegrator.MadiatorCore;
|
||||
using Telegrator.MadiatorCore.Descriptors;
|
||||
|
||||
namespace Telegrator.Handlers.Building
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal handler used for awaiting specific update types.
|
||||
/// Provides synchronization mechanism for waiting for updates of a particular type.
|
||||
/// </summary>
|
||||
/// <param name="handlingUpdateType">The type of update this awaiter handler waits for.</param>
|
||||
internal class AwaiterHandler(UpdateType handlingUpdateType) : UpdateHandlerBase(handlingUpdateType), IHandlerContainerFactory, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Manual reset event used for synchronization.
|
||||
/// </summary>
|
||||
private ManualResetEventSlim ResetEvent = new ManualResetEventSlim(false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the update that triggered this awaiter handler.
|
||||
/// </summary>
|
||||
public Update HandlingUpdate { get; private set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Waits for the specified update type to be received.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token to cancel the wait operation.</param>
|
||||
public void Wait(CancellationToken cancellationToken)
|
||||
{
|
||||
ResetEvent.Reset();
|
||||
ResetEvent.Wait(cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a handler container for this awaiter handler.
|
||||
/// </summary>
|
||||
/// <param name="_">The awaiting provider (unused).</param>
|
||||
/// <param name="describedHandler">The handler information containing the update.</param>
|
||||
/// <returns>An empty handler container.</returns>
|
||||
public IHandlerContainer CreateContainer(IAwaitingProvider _, DescribedHandlerInfo describedHandler)
|
||||
{
|
||||
HandlingUpdate = describedHandler.HandlingUpdate;
|
||||
return new EmptyHandlerContainer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the awaiter handler by setting the reset event.
|
||||
/// </summary>
|
||||
/// <param name="container">The handler container (unused).</param>
|
||||
/// <param name="cancellation">The cancellation token (unused).</param>
|
||||
/// <returns>A completed task.</returns>
|
||||
protected override Task ExecuteInternal(IHandlerContainer container, CancellationToken cancellation)
|
||||
{
|
||||
ResetEvent.Set();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes of the reset event.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
ResetEvent.Dispose();
|
||||
ResetEvent = null!;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegrator.Filters;
|
||||
using Telegrator.StateKeeping;
|
||||
using Telegrator.Handlers.Building.Components;
|
||||
using Telegrator.MadiatorCore;
|
||||
using Telegrator.MadiatorCore.Descriptors;
|
||||
using Telegrator.StateKeeping.Components;
|
||||
|
||||
namespace Telegrator.Handlers.Building
|
||||
{
|
||||
/// <summary>
|
||||
/// Builder class for creating awaiter handlers that can wait for specific update types.
|
||||
/// Provides fluent API for configuring filters, state keepers, and other handler properties.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUpdate">The type of update to await.</typeparam>
|
||||
public class AwaiterHandlerBuilder<TUpdate> : HandlerBuilderBase, IAwaiterHandlerBuilder<TUpdate> where TUpdate : class
|
||||
{
|
||||
/// <summary>
|
||||
/// The awaiting provider for managing handler registration.
|
||||
/// </summary>
|
||||
private readonly IAwaitingProvider HandlerProvider;
|
||||
|
||||
/// <summary>
|
||||
/// The update that triggered the awaiter creation.
|
||||
/// </summary>
|
||||
private readonly Update HandlingUpdate;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AwaiterHandlerBuilder{TUpdate}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="updateType">The type of update to await.</param>
|
||||
/// <param name="handlingUpdate">The update that triggered the awaiter creation.</param>
|
||||
/// <param name="handlerProvider">The awaiting provider for managing handler registration.</param>
|
||||
/// <exception cref="Exception">Thrown when the update type is not valid for TUpdate.</exception>
|
||||
public AwaiterHandlerBuilder(UpdateType updateType, Update handlingUpdate, IAwaitingProvider handlerProvider) : base(typeof(AwaiterHandler), updateType, null)
|
||||
{
|
||||
if (!updateType.IsValidUpdateObject<TUpdate>())
|
||||
throw new Exception();
|
||||
|
||||
HandlerProvider = handlerProvider;
|
||||
HandlingUpdate = handlingUpdate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Awaits for an update of the specified type using the default sender ID resolver.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The cancellation token to cancel the wait operation.</param>
|
||||
/// <returns>The awaited update of type TUpdate.</returns>
|
||||
public async Task<TUpdate> Await(CancellationToken cancellationToken = default)
|
||||
=> await Await(new SenderIdResolver(), cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Awaits for an update of the specified type using a custom state key resolver.
|
||||
/// </summary>
|
||||
/// <param name="keyResolver">The state key resolver to use for filtering updates.</param>
|
||||
/// <param name="cancellationToken">The cancellation token to cancel the wait operation.</param>
|
||||
/// <returns>The awaited update of type TUpdate.</returns>
|
||||
public async Task<TUpdate> Await(IStateKeyResolver<long> keyResolver, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Filters.Add(new StateKeyFilter<long>(keyResolver, keyResolver.ResolveKey(HandlingUpdate)));
|
||||
AwaiterHandler handlerInstance = new AwaiterHandler(UpdateType);
|
||||
HandlerDescriptor descriptor = BuildImplicitDescriptor(handlerInstance);
|
||||
|
||||
using (HandlerProvider.UseHandler(descriptor))
|
||||
{
|
||||
handlerInstance.Wait(cancellationToken);
|
||||
}
|
||||
|
||||
await Task.CompletedTask;
|
||||
return handlerInstance.HandlingUpdate.GetActualUpdateObject<TUpdate>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegrator.Handlers.Components;
|
||||
|
||||
namespace Telegrator.Handlers.Building
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal handler class that wraps a delegate action for execution.
|
||||
/// Used for dynamically created handlers that execute custom actions.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUpdate">The type of update being handled.</typeparam>
|
||||
internal class BuildedAbstractHandler<TUpdate> : AbstractUpdateHandler<TUpdate> where TUpdate : class
|
||||
{
|
||||
/// <summary>
|
||||
/// The delegate action to execute when the handler is invoked.
|
||||
/// </summary>
|
||||
private readonly AbstractHandlerAction<TUpdate> HandlerAction;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BuildedAbstractHandler{TUpdate}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="handlingUpdateType">The type of update this handler processes.</param>
|
||||
/// <param name="handlerAction">The delegate action to execute.</param>
|
||||
public BuildedAbstractHandler(UpdateType handlingUpdateType, AbstractHandlerAction<TUpdate> handlerAction) : base(handlingUpdateType)
|
||||
{
|
||||
HandlerAction = handlerAction;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the wrapped handler action.
|
||||
/// </summary>
|
||||
/// <param name="container">The handler container with execution context.</param>
|
||||
/// <param name="cancellation">The cancellation token.</param>
|
||||
/// <returns>A task representing the asynchronous execution.</returns>
|
||||
public override Task Execute(IAbstractHandlerContainer<TUpdate> container, CancellationToken cancellation)
|
||||
=> HandlerAction.Invoke(container, cancellation);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegrator.Annotations.StateKeeping;
|
||||
using Telegrator.Filters.Components;
|
||||
using Telegrator.Handlers.Components;
|
||||
using Telegrator.MadiatorCore;
|
||||
using Telegrator.MadiatorCore.Descriptors;
|
||||
using Telegrator.StateKeeping.Components;
|
||||
|
||||
namespace Telegrator.Handlers.Building.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for building handler descriptors and managing handler filters.
|
||||
/// </summary>
|
||||
public abstract class HandlerBuilderBase(Type buildingHandlerType, UpdateType updateType, IHandlersCollection? handlerCollection) : IHandlerBuilder
|
||||
{
|
||||
private static int HandlerServiceKeyIndex = 0;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="IHandlersCollection"/> to ehich new builded handlers is adding
|
||||
/// </summary>
|
||||
protected readonly IHandlersCollection? HandlerCollection = handlerCollection;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="UpdateType"/> of building handler
|
||||
/// </summary>
|
||||
protected readonly UpdateType UpdateType = updateType;
|
||||
|
||||
/// <summary>
|
||||
/// Type of handler to build
|
||||
/// </summary>
|
||||
protected readonly Type BuildingHandlerType = buildingHandlerType;
|
||||
|
||||
/// <summary>
|
||||
/// Filters applied to handler
|
||||
/// </summary>
|
||||
protected readonly List<IFilter<Update>> Filters = [];
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="DescriptorIndexer"/> of building handler
|
||||
/// </summary>
|
||||
protected DescriptorIndexer Indexer = new DescriptorIndexer(0, 0, 0);
|
||||
|
||||
/// <summary>
|
||||
/// Update validation filter of building handler
|
||||
/// </summary>
|
||||
protected IFilter<Update>? ValidateFilter;
|
||||
|
||||
/// <summary>
|
||||
/// State keeper of building handler
|
||||
/// </summary>
|
||||
protected IFilter<Update>? StateKeeper;
|
||||
|
||||
/// <summary>
|
||||
/// Builds an implicit <see cref="HandlerDescriptor"/> for the specified handler instance.
|
||||
/// </summary>
|
||||
/// <param name="instance">The <see cref="UpdateHandlerBase"/> instance.</param>
|
||||
/// <returns>The created <see cref="HandlerDescriptor"/>.</returns>
|
||||
protected HandlerDescriptor BuildImplicitDescriptor(UpdateHandlerBase instance)
|
||||
{
|
||||
object handlerServiceKey = GetImplicitHandlerServiceKey(BuildingHandlerType);
|
||||
|
||||
HandlerDescriptor descriptor = new HandlerDescriptor(
|
||||
DescriptorType.Implicit, BuildingHandlerType,
|
||||
UpdateType, Indexer, ValidateFilter,
|
||||
Filters.ToArray(), StateKeeper,
|
||||
handlerServiceKey, instance);
|
||||
|
||||
HandlerCollection?.AddDescriptor(descriptor);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a unique service key for an implicit handler type.
|
||||
/// </summary>
|
||||
/// <param name="BuildingHandlerType">The handler type.</param>
|
||||
/// <returns>A unique service key string.</returns>
|
||||
public static object GetImplicitHandlerServiceKey(Type BuildingHandlerType)
|
||||
=> string.Format("ImplicitHandler_{0}+{1}", HandlerServiceKeyIndex++, BuildingHandlerType.Name);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the update validating action for the handler.
|
||||
/// </summary>
|
||||
/// <param name="validateAction">The <see cref="UpdateValidateAction"/> to use.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void SetUpdateValidating(UpdateValidateAction validateAction)
|
||||
{
|
||||
ValidateFilter = new UpdateValidateFilter(validateAction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the concurrency level for the handler.
|
||||
/// </summary>
|
||||
/// <param name="concurrency">The concurrency value.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void SetConcurreny(int concurrency)
|
||||
{
|
||||
Indexer = Indexer.UpdateConcurrency(concurrency);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the priority for the handler.
|
||||
/// </summary>
|
||||
/// <param name="priority">The priority value.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void SetPriority(int priority)
|
||||
{
|
||||
Indexer = Indexer.UpdatePriority(priority);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets both concurrency and priority for the handler.
|
||||
/// </summary>
|
||||
/// <param name="concurrency">The concurrency value.</param>
|
||||
/// <param name="priority">The priority value.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void SetIndexer(int concurrency, int priority)
|
||||
{
|
||||
Indexer = new DescriptorIndexer(0, concurrency, priority);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a filter to the handler.
|
||||
/// </summary>
|
||||
/// <param name="filter">The <see cref="IFilter{Update}"/> to add.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void AddFilter(IFilter<Update> filter)
|
||||
{
|
||||
Filters.Add(filter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds multiple filters to the handler.
|
||||
/// </summary>
|
||||
/// <param name="filters">The filters to add.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void AddFilters(params IFilter<Update>[] filters)
|
||||
{
|
||||
Filters.AddRange(filters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a state keeper for the handler using a specific state and key resolver.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">The type of the key.</typeparam>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="TKeeper">The type of the state keeper.</typeparam>
|
||||
/// <param name="myState">The state value.</param>
|
||||
/// <param name="keyResolver">The key resolver.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void SetStateKeeper<TKey, TState, TKeeper>(TState myState, IStateKeyResolver<TKey> keyResolver)
|
||||
where TKey : notnull
|
||||
where TState : IEquatable<TState>
|
||||
where TKeeper : StateKeeperBase<TKey, TState>, new()
|
||||
{
|
||||
StateKeeper = new StateKeepFilter<TKey, TState, TKeeper>(myState, keyResolver);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a state keeper for the handler using a special state and key resolver.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">The type of the key.</typeparam>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="TKeeper">The type of the state keeper.</typeparam>
|
||||
/// <param name="specialState">The special state value.</param>
|
||||
/// <param name="keyResolver">The key resolver.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void SetStateKeeper<TKey, TState, TKeeper>(SpecialState specialState, IStateKeyResolver<TKey> keyResolver)
|
||||
where TKey : notnull
|
||||
where TState : IEquatable<TState>
|
||||
where TKeeper : StateKeeperBase<TKey, TState>, new()
|
||||
{
|
||||
StateKeeper = new StateKeepFilter<TKey, TState, TKeeper>(specialState, keyResolver);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a targeted filter for a specific filter target type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TFilterTarget">The type of the filter target.</typeparam>
|
||||
/// <param name="getFilterringTarget">Function to get the filter target from an update.</param>
|
||||
/// <param name="filter">The filter to add.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void AddTargetedFilter<TFilterTarget>(Func<Update, TFilterTarget?> getFilterringTarget, IFilter<TFilterTarget> filter) where TFilterTarget : class
|
||||
{
|
||||
AnonymousTypeFilter anonymousTypeFilter = AnonymousTypeFilter.Compile(filter, getFilterringTarget);
|
||||
Filters.Add(anonymousTypeFilter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds multiple targeted filters for a specific filter target type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TFilterTarget">The type of the filter target.</typeparam>
|
||||
/// <param name="getFilterringTarget">Function to get the filter target from an update.</param>
|
||||
/// <param name="filters">The filters to add.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void AddTargetedFilters<TFilterTarget>(Func<Update, TFilterTarget?> getFilterringTarget, params IFilter<TFilterTarget>[] filters) where TFilterTarget : class
|
||||
{
|
||||
AnonymousCompiledFilter compiledPollingFilter = AnonymousCompiledFilter.Compile(filters, getFilterringTarget);
|
||||
Filters.Add(compiledPollingFilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Telegrator.StateKeeping.Components;
|
||||
|
||||
namespace Telegrator.Handlers.Building.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a builder for awaiting handler logic for a specific update type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUpdate">The type of update to await.</typeparam>
|
||||
public interface IAwaiterHandlerBuilder<TUpdate> : IHandlerBuilder where TUpdate : class
|
||||
{
|
||||
/// <summary>
|
||||
/// Awaits an update using the specified key resolver and cancellation token.
|
||||
/// </summary>
|
||||
/// <param name="keyResolver">The <see cref="IStateKeyResolver{TKey}"/> to resolve the key.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A <see cref="Task{TUpdate}"/> representing the awaited update.</returns>
|
||||
public Task<TUpdate> Await(IStateKeyResolver<long> keyResolver, CancellationToken cancellationToken = default);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using Telegram.Bot.Types;
|
||||
using Telegrator.Annotations.StateKeeping;
|
||||
using Telegrator.Filters.Components;
|
||||
using Telegrator.StateKeeping.Components;
|
||||
|
||||
namespace Telegrator.Handlers.Building.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines builder actions for configuring handler builders.
|
||||
/// </summary>
|
||||
public interface IHandlerBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the update validating action for the handler.
|
||||
/// </summary>
|
||||
/// <param name="validateAction">The <see cref="UpdateValidateAction"/> to use.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void SetUpdateValidating(UpdateValidateAction validateAction);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the concurrency level for the handler.
|
||||
/// </summary>
|
||||
/// <param name="concurrency">The concurrency value.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void SetConcurreny(int concurrency);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the priority for the handler.
|
||||
/// </summary>
|
||||
/// <param name="priority">The priority value.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void SetPriority(int priority);
|
||||
|
||||
/// <summary>
|
||||
/// Sets both concurrency and priority for the handler.
|
||||
/// </summary>
|
||||
/// <param name="concurrency">The concurrency value.</param>
|
||||
/// <param name="priority">The priority value.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void SetIndexer(int concurrency, int priority);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a filter to the handler.
|
||||
/// </summary>
|
||||
/// <param name="filter">The <see cref="IFilter{Update}"/> to add.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void AddFilter(IFilter<Update> filter);
|
||||
|
||||
/// <summary>
|
||||
/// Adds multiple filters to the handler.
|
||||
/// </summary>
|
||||
/// <param name="filters">The filters to add.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void AddFilters(params IFilter<Update>[] filters);
|
||||
|
||||
/// <summary>
|
||||
/// Sets a state keeper for the handler using a specific state and key resolver.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">The type of the key.</typeparam>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="TKeeper">The type of the state keeper.</typeparam>
|
||||
/// <param name="myState">The state value.</param>
|
||||
/// <param name="keyResolver">The key resolver.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void SetStateKeeper<TKey, TState, TKeeper>(TState myState, IStateKeyResolver<TKey> keyResolver)
|
||||
where TKey : notnull
|
||||
where TState : IEquatable<TState>
|
||||
where TKeeper : StateKeeperBase<TKey, TState>, new();
|
||||
|
||||
/// <summary>
|
||||
/// Sets a state keeper for the handler using a special state and key resolver.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">The type of the key.</typeparam>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="TKeeper">The type of the state keeper.</typeparam>
|
||||
/// <param name="specialState">The special state value.</param>
|
||||
/// <param name="keyResolver">The key resolver.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void SetStateKeeper<TKey, TState, TKeeper>(SpecialState specialState, IStateKeyResolver<TKey> keyResolver)
|
||||
where TKey : notnull
|
||||
where TState : IEquatable<TState>
|
||||
where TKeeper : StateKeeperBase<TKey, TState>, new();
|
||||
|
||||
/// <summary>
|
||||
/// Adds a targeted filter for a specific filter target type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TFilterTarget">The type of the filter target.</typeparam>
|
||||
/// <param name="getFilterringTarget">Function to get the filter target from an update.</param>
|
||||
/// <param name="filter">The filter to add.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void AddTargetedFilter<TFilterTarget>(Func<Update, TFilterTarget?> getFilterringTarget, IFilter<TFilterTarget> filter)
|
||||
where TFilterTarget : class;
|
||||
|
||||
/// <summary>
|
||||
/// Adds multiple targeted filters for a specific filter target type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TFilterTarget">The type of the filter target.</typeparam>
|
||||
/// <param name="getFilterringTarget">Function to get the filter target from an update.</param>
|
||||
/// <param name="filters">The filters to add.</param>
|
||||
/// <returns>The builder instance.</returns>
|
||||
public void AddTargetedFilters<TFilterTarget>(Func<Update, TFilterTarget?> getFilterringTarget, params IFilter<TFilterTarget>[] filters)
|
||||
where TFilterTarget : class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Telegrator.Handlers.Building;
|
||||
using Telegrator.MadiatorCore;
|
||||
|
||||
namespace Telegrator.Handlers.Building.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a builder for regular handler logic for a specific update type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUpdate">The type of update to handle.</typeparam>
|
||||
public interface IRegularHandlerBuilder<TUpdate> : IHandlerBuilder where TUpdate : class
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds the handler logic using the specified execution delegate.
|
||||
/// </summary>
|
||||
/// <param name="executeHandler">The delegate to execute the handler logic.</param>
|
||||
public IHandlersCollection Build(AbstractHandlerAction<TUpdate> executeHandler);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using Telegram.Bot.Types;
|
||||
using Telegrator.Annotations.StateKeeping;
|
||||
using Telegrator.Filters;
|
||||
using Telegrator.Filters.Components;
|
||||
using Telegrator.StateKeeping.Components;
|
||||
|
||||
namespace Telegrator.Handlers.Building.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Filter for state keeping logic, allowing filtering based on state and special state conditions.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">The type of the key for state resolution.</typeparam>
|
||||
/// <typeparam name="TState">The type of the state.</typeparam>
|
||||
/// <typeparam name="TKeeper">The type of the state keeper.</typeparam>
|
||||
public class StateKeepFilter<TKey, TState, TKeeper> : Filter<Update>
|
||||
where TKey : notnull
|
||||
where TState : IEquatable<TState>
|
||||
where TKeeper : StateKeeperBase<TKey, TState>, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the state keeper instance.
|
||||
/// </summary>
|
||||
public static TKeeper StateKeeper { get; internal set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the state value for this filter.
|
||||
/// </summary>
|
||||
public TState MyState { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the special state value for this filter.
|
||||
/// </summary>
|
||||
public SpecialState SpecialState { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StateKeepFilter{TKey, TState, TKeeper}"/> class with a specific state.
|
||||
/// </summary>
|
||||
/// <param name="myState">The state value.</param>
|
||||
/// <param name="keyResolver">The key resolver.</param>
|
||||
public StateKeepFilter(TState myState, IStateKeyResolver<TKey> keyResolver)
|
||||
{
|
||||
StateKeeper ??= new TKeeper();
|
||||
StateKeeper.KeyResolver = keyResolver;
|
||||
MyState = myState;
|
||||
SpecialState = SpecialState.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StateKeepFilter{TKey, TState, TKeeper}"/> class with a special state.
|
||||
/// </summary>
|
||||
/// <param name="specialState">The special state value.</param>
|
||||
/// <param name="keyResolver">The key resolver.</param>
|
||||
public StateKeepFilter(SpecialState specialState, IStateKeyResolver<TKey> keyResolver)
|
||||
{
|
||||
StateKeeper ??= new TKeeper();
|
||||
StateKeeper.KeyResolver = keyResolver;
|
||||
MyState = StateKeeper.DefaultState;
|
||||
SpecialState = specialState;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the filter can pass for the given context based on state logic.
|
||||
/// </summary>
|
||||
/// <param name="context">The filter execution context.</param>
|
||||
/// <returns>True if the filter passes; otherwise, false.</returns>
|
||||
public override bool CanPass(FilterExecutionContext<Update> context)
|
||||
{
|
||||
if (SpecialState == SpecialState.AnyState)
|
||||
return true;
|
||||
|
||||
if (!StateKeeper.TryGetState(context.Input, out TState? state))
|
||||
return SpecialState == SpecialState.NoState;
|
||||
|
||||
if (state == null)
|
||||
return false;
|
||||
|
||||
return MyState.Equals(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using Telegram.Bot.Types;
|
||||
using Telegrator.Filters.Components;
|
||||
|
||||
namespace Telegrator.Handlers.Building.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Delegate for validating an update in a filter context.
|
||||
/// </summary>
|
||||
/// <param name="context">The filter execution context.</param>
|
||||
/// <returns>True if the update is valid; otherwise, false.</returns>
|
||||
public delegate bool UpdateValidateAction(FilterExecutionContext<Update> context);
|
||||
|
||||
/// <summary>
|
||||
/// Filter that uses a delegate to validate updates.
|
||||
/// </summary>
|
||||
public class UpdateValidateFilter : IFilter<Update>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this filter is collectable. Always false for this filter.
|
||||
/// </summary>
|
||||
public bool IsCollectible => false;
|
||||
private readonly UpdateValidateAction UpdateValidateAction;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UpdateValidateFilter"/> class.
|
||||
/// </summary>
|
||||
/// <param name="updateValidateAction">The validation delegate to use.</param>
|
||||
public UpdateValidateFilter(UpdateValidateAction updateValidateAction)
|
||||
{
|
||||
UpdateValidateAction = updateValidateAction;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the filter can pass for the given context using the validation delegate.
|
||||
/// </summary>
|
||||
/// <param name="info">The filter execution context.</param>
|
||||
/// <returns>True if the filter passes; otherwise, false.</returns>
|
||||
public bool CanPass(FilterExecutionContext<Update> info)
|
||||
=> UpdateValidateAction.Invoke(info);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegrator.Providers;
|
||||
using Telegrator.Handlers.Building.Components;
|
||||
using Telegrator.MadiatorCore;
|
||||
|
||||
namespace Telegrator.Handlers.Building
|
||||
{
|
||||
/// <summary>
|
||||
/// Delegate for handler execution actions that take a container and cancellation token.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUpdate">The type of update being handled.</typeparam>
|
||||
/// <param name="container">The handler container with execution context.</param>
|
||||
/// <param name="cancellation">The cancellation token.</param>
|
||||
/// <returns>A task representing the asynchronous execution.</returns>
|
||||
public delegate Task AbstractHandlerAction<TUpdate>(IAbstractHandlerContainer<TUpdate> container, CancellationToken cancellation) where TUpdate : class;
|
||||
|
||||
/// <summary>
|
||||
/// Builder class for creating regular handlers that can process updates.
|
||||
/// Provides fluent API for configuring filters, state keepers, and other handler properties.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUpdate">The type of update to handle.</typeparam>
|
||||
public class HandlerBuilder<TUpdate> : HandlerBuilderBase, IRegularHandlerBuilder<TUpdate> where TUpdate : class
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HandlerBuilder{TUpdate}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="updateType">The type of update this handler will process.</param>
|
||||
/// <param name="handlerCollection">The collection to register the built handler with.</param>
|
||||
/// <exception cref="ArgumentException">Thrown when the update type is not valid for TUpdate.</exception>
|
||||
public HandlerBuilder(UpdateType updateType, IHandlersCollection handlerCollection) : base(typeof(BuildedAbstractHandler<TUpdate>), updateType, handlerCollection)
|
||||
{
|
||||
if (!updateType.IsValidUpdateObject<TUpdate>())
|
||||
throw new ArgumentException("\"UpdateType." + updateType + "\" is not valid type for \"" + nameof(TUpdate) + "\" update object", nameof(updateType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds an abstract handler with the specified execution action.
|
||||
/// </summary>
|
||||
/// <param name="executeHandler">The delegate action to execute when the handler is invoked.</param>
|
||||
/// <exception cref="ArgumentNullException">Thrown when executeHandler is null.</exception>
|
||||
public IHandlersCollection Build(AbstractHandlerAction<TUpdate> executeHandler)
|
||||
{
|
||||
if (executeHandler == null)
|
||||
throw new ArgumentNullException(nameof(executeHandler));
|
||||
|
||||
BuildedAbstractHandler<TUpdate> instance = new BuildedAbstractHandler<TUpdate>(UpdateType, executeHandler);
|
||||
BuildImplicitDescriptor(instance);
|
||||
return HandlerCollection!;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegrator.Attributes;
|
||||
using Telegrator.Filters.Components;
|
||||
using Telegrator.Handlers.Components;
|
||||
|
||||
namespace Telegrator.Handlers
|
||||
{
|
||||
/// <summary>
|
||||
/// Attribute that marks a handler to process callback query updates.
|
||||
/// This handler will be triggered when users interact with inline keyboards or other callback mechanisms.
|
||||
/// </summary>
|
||||
/// <param name="concurrency">The maximum number of concurrent executions allowed (default: 0 for unlimited).</param>
|
||||
public sealed class CallbackQueryHandlerAttribute(int concurrency = 0) : UpdateHandlerAttribute<CallbackQueryHandler>(UpdateType.CallbackQuery, concurrency)
|
||||
{
|
||||
/// <summary>
|
||||
/// Always returns true, allowing any callback query update to pass through this filter.
|
||||
/// </summary>
|
||||
/// <param name="context">The filter execution context (unused).</param>
|
||||
/// <returns>Always returns true to allow any callback query update.</returns>
|
||||
public override bool CanPass(FilterExecutionContext<Update> context) => true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract base class for handlers that process callback query updates.
|
||||
/// Provides a foundation for creating handlers that respond to user interactions with inline keyboards.
|
||||
/// </summary>
|
||||
public abstract class CallbackQueryHandler() : AbstractUpdateHandler<CallbackQuery>(UpdateType.CallbackQuery)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the type-specific data from the callback query.
|
||||
/// Returns the data string, chat instance, or game short name depending on the callback query type.
|
||||
/// </summary>
|
||||
protected string TypeData
|
||||
{
|
||||
get => Input switch
|
||||
{
|
||||
{ Data: { } data } => data,
|
||||
{ ChatInstance: { } chatInstance } => chatInstance,
|
||||
{ GameShortName: { } gameShortName } => gameShortName
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegrator.Attributes;
|
||||
using Telegrator.Filters.Components;
|
||||
|
||||
namespace Telegrator.Handlers
|
||||
{
|
||||
/// <summary>
|
||||
/// Attribute that marks a handler to process command messages.
|
||||
/// This handler will be triggered when users send bot commands (messages starting with '/').
|
||||
/// </summary>
|
||||
/// <param name="concurrency">The maximum number of concurrent executions allowed (default: 1).</param>
|
||||
public class CommandHandlerAttribute(int concurrency = 1) : UpdateHandlerAttribute<CommandHandler>(UpdateType.Message, concurrency)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the command that was extracted from the message (without the '/' prefix and bot username).
|
||||
/// </summary>
|
||||
public string ReceivedCommand { get; private set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the update contains a valid bot command and extracts the command text.
|
||||
/// </summary>
|
||||
/// <param name="context">The filter execution context containing the update.</param>
|
||||
/// <returns>True if the update contains a valid bot command; otherwise, false.</returns>
|
||||
public override bool CanPass(FilterExecutionContext<Update> context)
|
||||
{
|
||||
if (context.Input.Message is not { Entities.Length: > 0, Text.Length: > 0 } message)
|
||||
return false;
|
||||
|
||||
MessageEntity commandEntity = message.Entities[0];
|
||||
if (commandEntity.Type != MessageEntityType.BotCommand)
|
||||
return false;
|
||||
|
||||
ReceivedCommand = message.Text.Substring(commandEntity.Offset + 1, commandEntity.Length - 1);
|
||||
if (ReceivedCommand.Contains('@'))
|
||||
{
|
||||
string[] split = ReceivedCommand.Split('@');
|
||||
ReceivedCommand = split[0];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract base class for handlers that process command messages.
|
||||
/// Provides functionality to extract and parse command arguments.
|
||||
/// </summary>
|
||||
public abstract class CommandHandler : MessageHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Cached array of command arguments.
|
||||
/// </summary>
|
||||
private string[]? _cmdArgsSplit;
|
||||
|
||||
/// <summary>
|
||||
/// Cached string representation of command arguments.
|
||||
/// </summary>
|
||||
private string? _argsString;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the command that was extracted from the message.
|
||||
/// </summary>
|
||||
protected string ReceivedCommand
|
||||
{
|
||||
get => CompletedFilters.Get<CommandHandlerAttribute>(0).ReceivedCommand;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the arguments string (everything after the command).
|
||||
/// </summary>
|
||||
protected string ArgumentsString
|
||||
{
|
||||
get => _argsString ??= ArgsStringify();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the command arguments as an array of strings.
|
||||
/// </summary>
|
||||
protected string[] Arguments
|
||||
{
|
||||
get => _cmdArgsSplit ??= SplitArgs();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Splits the command arguments into an array of strings.
|
||||
/// </summary>
|
||||
/// <returns>An array of command arguments.</returns>
|
||||
private string[] SplitArgs()
|
||||
{
|
||||
if (Input.Text is not { Length: > 0 })
|
||||
return [];
|
||||
|
||||
return Input.Text.Split([" "], StringSplitOptions.RemoveEmptyEntries).Skip(1).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the arguments string from the command message.
|
||||
/// </summary>
|
||||
/// <returns>The arguments string (everything after the command).</returns>
|
||||
private string ArgsStringify()
|
||||
{
|
||||
if (Input.Text is not { Length: > 0 })
|
||||
return string.Empty;
|
||||
|
||||
return Input.Text.Substring(ReceivedCommand.Length + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract base class for branching handlers that process command messages.
|
||||
/// Provides functionality to extract and parse command arguments for branching scenarios.
|
||||
/// </summary>
|
||||
public abstract class BranchingCommandHandler : BranchingMessageHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Cached array of command arguments.
|
||||
/// </summary>
|
||||
private string[]? _cmdArgsSplit;
|
||||
|
||||
/// <summary>
|
||||
/// Cached string representation of command arguments.
|
||||
/// </summary>
|
||||
private string? _argsString;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the command that was extracted from the message.
|
||||
/// </summary>
|
||||
protected string ReceivedCommand
|
||||
{
|
||||
get => CompletedFilters.Get<CommandHandlerAttribute>(0).ReceivedCommand;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the arguments string (everything after the command).
|
||||
/// </summary>
|
||||
protected string ArgumentsString
|
||||
{
|
||||
get => _argsString ??= ArgsStringify();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the command arguments as an array of strings.
|
||||
/// </summary>
|
||||
protected string[] Arguments
|
||||
{
|
||||
get => _cmdArgsSplit ??= SplitArgs();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Splits the command arguments into an array of strings.
|
||||
/// </summary>
|
||||
/// <returns>An array of command arguments.</returns>
|
||||
private string[] SplitArgs()
|
||||
{
|
||||
if (Input.Text is not { Length: > 0 })
|
||||
return [];
|
||||
|
||||
return Input.Text.Split([" "], StringSplitOptions.RemoveEmptyEntries).Skip(1).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the arguments string from the command message.
|
||||
/// </summary>
|
||||
/// <returns>The arguments string (everything after the command).</returns>
|
||||
private string ArgsStringify()
|
||||
{
|
||||
if (Input.Text is not { Length: > 0 })
|
||||
return string.Empty;
|
||||
|
||||
return Input.Text.Substring(ReceivedCommand.Length + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegrator.Filters.Components;
|
||||
using Telegrator.MadiatorCore;
|
||||
using Telegrator.MadiatorCore.Descriptors;
|
||||
|
||||
namespace Telegrator.Handlers.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract handler for Telegram updates of type <typeparamref name="TUpdate"/>.
|
||||
/// </summary>
|
||||
public abstract class AbstractUpdateHandler<TUpdate> : UpdateHandlerBase, IHandlerContainerFactory where TUpdate : class
|
||||
{
|
||||
/// <summary>
|
||||
/// Handler container for the current update.
|
||||
/// </summary>
|
||||
protected IAbstractHandlerContainer<TUpdate> Container { get; private set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Telegram Bot client associated with the current container.
|
||||
/// </summary>
|
||||
protected ITelegramBotClient Client => Container.Client;
|
||||
|
||||
/// <summary>
|
||||
/// Incoming update of type <typeparamref name="TUpdate"/>.
|
||||
/// </summary>
|
||||
protected TUpdate Input => Container.ActualUpdate;
|
||||
|
||||
/// <summary>
|
||||
/// The Telegram update being handled.
|
||||
/// </summary>
|
||||
protected Update HandlingUpdate => Container.HandlingUpdate;
|
||||
|
||||
/// <summary>
|
||||
/// Additional data associated with the handler execution.
|
||||
/// </summary>
|
||||
protected Dictionary<string, object> ExtraData => Container.ExtraData;
|
||||
|
||||
/// <summary>
|
||||
/// List of successfully passed filters.
|
||||
/// </summary>
|
||||
protected CompletedFiltersList CompletedFilters => Container.CompletedFilters;
|
||||
|
||||
/// <summary>
|
||||
/// Provider for awaiting asynchronous operations.
|
||||
/// </summary>
|
||||
protected IAwaitingProvider AwaitingProvider => Container.AwaitingProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance and checks that the update type matches <typeparamref name="TUpdate"/>.
|
||||
/// </summary>
|
||||
/// <param name="handlingUpdateType">The type of update to handle.</param>
|
||||
protected AbstractUpdateHandler(UpdateType handlingUpdateType) : base(handlingUpdateType)
|
||||
{
|
||||
if (!HandlingUpdateType.IsValidUpdateObject<TUpdate>())
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a handler container for the specified awaiting provider and handler info.
|
||||
/// </summary>
|
||||
/// <param name="awaitingProvider">The awaiting provider.</param>
|
||||
/// <param name="handlerInfo">The handler descriptor info.</param>
|
||||
/// <returns>The created handler container.</returns>
|
||||
public virtual IHandlerContainer CreateContainer(IAwaitingProvider awaitingProvider, DescribedHandlerInfo handlerInfo)
|
||||
{
|
||||
return new AbstractHandlerContainer<TUpdate>(awaitingProvider, handlerInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the handler logic using the specified container.
|
||||
/// </summary>
|
||||
/// <param name="container">The handler container.</param>
|
||||
/// <param name="cancellationToken">Cancellation token.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
protected override sealed async Task ExecuteInternal(IHandlerContainer container, CancellationToken cancellationToken)
|
||||
{
|
||||
Container = (IAbstractHandlerContainer<TUpdate>)container;
|
||||
await Execute(Container, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract method to execute the update handling logic.
|
||||
/// </summary>
|
||||
/// <param name="container">The handler container.</param>
|
||||
/// <param name="cancellation">Cancellation token.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
public abstract Task Execute(IAbstractHandlerContainer<TUpdate> container, CancellationToken cancellation);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
using System.Reflection;
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegrator.Attributes.Components;
|
||||
using Telegrator.Filters.Components;
|
||||
using Telegrator.MadiatorCore;
|
||||
using Telegrator.MadiatorCore.Descriptors;
|
||||
using Telegrator.Providers;
|
||||
|
||||
namespace Telegrator.Handlers.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract base class for handlers that support branching execution based on different methods.
|
||||
/// Allows multiple handler methods to be defined in a single class, each with its own filters.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUpdate">The type of update being handled.</typeparam>
|
||||
public abstract class BranchingUpdateHandler<TUpdate> : AbstractUpdateHandler<TUpdate>, IHandlerContainerFactory, ICustomDescriptorsProvider where TUpdate : class
|
||||
{
|
||||
/// <summary>
|
||||
/// The method info for the current branch being executed.
|
||||
/// </summary>
|
||||
private MethodInfo? branchMethodInfo = null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the binding flags used to discover branch methods.
|
||||
/// </summary>
|
||||
protected virtual BindingFlags BranchesBindingFlags => BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the allowed return types for branch methods.
|
||||
/// </summary>
|
||||
protected virtual Type[] AllowedBranchReturnTypes => [typeof(void), typeof(Task)];
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cancellation token for the current execution.
|
||||
/// </summary>
|
||||
protected CancellationToken Cancellation { get; private set; } = default;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BranchingUpdateHandler{TUpdate}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="handlingUpdateType">The type of update this handler processes.</param>
|
||||
protected BranchingUpdateHandler(UpdateType handlingUpdateType)
|
||||
: base(handlingUpdateType) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BranchingUpdateHandler{TUpdate}"/> class with a specific branch method.
|
||||
/// </summary>
|
||||
/// <param name="handlingUpdateType">The type of update this handler processes.</param>
|
||||
/// <param name="branch">The specific branch method to execute.</param>
|
||||
protected BranchingUpdateHandler(UpdateType handlingUpdateType, MethodInfo branch)
|
||||
: base(handlingUpdateType) => branchMethodInfo = branch;
|
||||
|
||||
/// <summary>
|
||||
/// Describes all handler branches in this class.
|
||||
/// </summary>
|
||||
/// <returns>A collection of handler descriptors for each branch method.</returns>
|
||||
/// <exception cref="Exception">Thrown when no branch methods are found.</exception>
|
||||
public IEnumerable<HandlerDescriptor> DescribeHandlers()
|
||||
{
|
||||
Type thisType = GetType();
|
||||
UpdateHandlerAttributeBase updateHandlerAttribute = HandlerInspector.GetHandlerAttribute(thisType);
|
||||
IEnumerable<IFilter<Update>> handlerFilters = HandlerInspector.GetFilterAttributes(thisType, HandlingUpdateType);
|
||||
|
||||
MethodInfo[] handlerBranches = thisType.GetMethods().Where(branch => branch.DeclaringType == thisType).ToArray();
|
||||
if (handlerBranches.Length == 0)
|
||||
throw new Exception();
|
||||
|
||||
foreach (MethodInfo branch in handlerBranches)
|
||||
yield return DescribeBranch(branch, updateHandlerAttribute, handlerFilters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Describes a specific branch method.
|
||||
/// </summary>
|
||||
/// <param name="branch">The branch method to describe.</param>
|
||||
/// <param name="handlerAttribute">The handler attribute for the class.</param>
|
||||
/// <param name="handlerFilters">The filters applied to the class.</param>
|
||||
/// <returns>A handler descriptor for the branch method.</returns>
|
||||
/// <exception cref="Exception">Thrown when the branch method has parameters or invalid return type.</exception>
|
||||
protected virtual HandlerDescriptor DescribeBranch(MethodInfo branch, UpdateHandlerAttributeBase handlerAttribute, IEnumerable<IFilter<Update>> handlerFilters)
|
||||
{
|
||||
Type thisType = GetType();
|
||||
|
||||
if (branch.GetParameters().Length != 0)
|
||||
throw new Exception();
|
||||
|
||||
if (!AllowedBranchReturnTypes.Any(branch.ReturnType.Equals))
|
||||
throw new Exception();
|
||||
|
||||
List<IFilter<Update>> branchFiltersList = HandlerInspector.GetFilterAttributes(branch, HandlingUpdateType).ToList();
|
||||
branchFiltersList.AddRange(handlerFilters);
|
||||
|
||||
DescriptorFiltersSet filtersSet = new DescriptorFiltersSet(
|
||||
handlerAttribute,
|
||||
HandlerInspector.GetStateKeeperAttribute(branch),
|
||||
branchFiltersList.ToArray());
|
||||
|
||||
return new HandlerBranchDescriptor(branch, HandlingUpdateType, handlerAttribute.GetIndexer(), filtersSet);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a handler container for this branching handler.
|
||||
/// </summary>
|
||||
/// <param name="awaitingProvider">The awaiting provider for the container.</param>
|
||||
/// <param name="handlerInfo">The handler information.</param>
|
||||
/// <returns>A handler container for this branching handler.</returns>
|
||||
/// <exception cref="Exception">Thrown when the awaiting provider is not of the expected type.</exception>
|
||||
public override IHandlerContainer CreateContainer(IAwaitingProvider awaitingProvider, DescribedHandlerInfo handlerInfo)
|
||||
{
|
||||
return new AbstractHandlerContainer<TUpdate>(awaitingProvider, handlerInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the current branch method.
|
||||
/// </summary>
|
||||
/// <param name="container">The handler container.</param>
|
||||
/// <param name="cancellation">The cancellation token.</param>
|
||||
/// <exception cref="Exception">Thrown when no branch method is set.</exception>
|
||||
public override async Task Execute(IAbstractHandlerContainer<TUpdate> container, CancellationToken cancellation)
|
||||
{
|
||||
if (branchMethodInfo is null)
|
||||
throw new Exception();
|
||||
|
||||
Cancellation = cancellation;
|
||||
await BranchExecuteWrapper(container, branchMethodInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps the execution of a branch method, handling both void and Task return types.
|
||||
/// </summary>
|
||||
/// <param name="container">The handler container.</param>
|
||||
/// <param name="methodInfo">The method to execute.</param>
|
||||
protected virtual async Task BranchExecuteWrapper(IAbstractHandlerContainer<TUpdate> container, MethodInfo methodInfo)
|
||||
{
|
||||
if (methodInfo.ReturnType == typeof(void))
|
||||
{
|
||||
methodInfo.Invoke(this, []);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
object branchReturn = methodInfo.Invoke(this, []);
|
||||
if (branchReturn == null)
|
||||
return;
|
||||
|
||||
if (branchReturn is Task branchTask)
|
||||
await branchTask;
|
||||
}
|
||||
}
|
||||
|
||||
private class HandlerBranchDescriptor : HandlerDescriptor
|
||||
{
|
||||
public HandlerBranchDescriptor(MethodInfo method, UpdateType updateType, DescriptorIndexer indexer, DescriptorFiltersSet filters)
|
||||
: base(DescriptorType.General, method.DeclaringType, updateType, indexer, filters)
|
||||
{
|
||||
DisplayString = string.Format("{0}+{1}", method.DeclaringType.Name, method.Name);
|
||||
InstanceFactory = () =>
|
||||
{
|
||||
BranchingUpdateHandler<TUpdate> handler = (BranchingUpdateHandler<TUpdate>)Activator.CreateInstance(method.DeclaringType);
|
||||
handler.branchMethodInfo = method;
|
||||
return handler;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Types;
|
||||
using Telegrator.Filters.Components;
|
||||
using Telegrator.MadiatorCore;
|
||||
|
||||
namespace Telegrator.Handlers.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an empty handler container that throws <see cref="NotImplementedException"/> for all members.
|
||||
/// </summary>
|
||||
public class EmptyHandlerContainer : IHandlerContainer
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public Update HandlingUpdate => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ITelegramBotClient Client => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<string, object> ExtraData => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public CompletedFiltersList CompletedFilters => throw new NotImplementedException();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IAwaitingProvider AwaitingProvider => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Types;
|
||||
using Telegrator.Filters.Components;
|
||||
using Telegrator.MadiatorCore;
|
||||
|
||||
namespace Telegrator.Handlers.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for handler containers that provide context and resources for update handlers.
|
||||
/// Contains all necessary information and services that handlers need during execution.
|
||||
/// </summary>
|
||||
public interface IHandlerContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Update"/> being handled.
|
||||
/// </summary>
|
||||
public Update HandlingUpdate { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ITelegramBotClient"/> used for this handler.
|
||||
/// </summary>
|
||||
public ITelegramBotClient Client { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the extra data associated with the handler execution.
|
||||
/// </summary>
|
||||
public Dictionary<string, object> ExtraData { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="CompletedFiltersList"/> for this handler.
|
||||
/// </summary>
|
||||
public CompletedFiltersList CompletedFilters { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IAwaitingProvider"/> for awaiting operations.
|
||||
/// </summary>
|
||||
public IAwaitingProvider AwaitingProvider { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using Telegrator.MadiatorCore;
|
||||
using Telegrator.MadiatorCore.Descriptors;
|
||||
|
||||
namespace Telegrator.Handlers.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Factory interface for creating handler containers.
|
||||
/// Provides a way to create handler containers with specific providers and handler information.
|
||||
/// </summary>
|
||||
public interface IHandlerContainerFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="IHandlerContainer"/> for the specified awaiting provider and handler info.
|
||||
/// </summary>
|
||||
/// <param name="awaitingProvider">The <see cref="IAwaitingProvider"/> to use.</param>
|
||||
/// <param name="handlerInfo">The <see cref="DescribedHandlerInfo"/> for the handler.</param>
|
||||
/// <returns>A new <see cref="IHandlerContainer"/> instance.</returns>
|
||||
public IHandlerContainer CreateContainer(IAwaitingProvider awaitingProvider, DescribedHandlerInfo handlerInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegrator.MadiatorCore.Descriptors;
|
||||
|
||||
namespace Telegrator.Handlers.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for update handlers, providing execution and lifetime management for Telegram updates.
|
||||
/// </summary>
|
||||
public abstract class UpdateHandlerBase(UpdateType handlingUpdateType)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="UpdateType"/> that this handler processes.
|
||||
/// </summary>
|
||||
public UpdateType HandlingUpdateType { get; } = handlingUpdateType;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="HandlerLifetimeToken"/> associated with this handler instance.
|
||||
/// </summary>
|
||||
public HandlerLifetimeToken LifetimeToken { get; } = new HandlerLifetimeToken();
|
||||
|
||||
/// <summary>
|
||||
/// Executes the handler logic and marks the lifetime as ended after execution.
|
||||
/// </summary>
|
||||
/// <param name="container">The <see cref="IHandlerContainer"/> for the update.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public async Task Execute(IHandlerContainer container, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await ExecuteInternal(container, cancellationToken);
|
||||
LifetimeToken.LifetimeEnded();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the handler logic for the given container and cancellation token.
|
||||
/// </summary>
|
||||
/// <param name="container">The <see cref="IHandlerContainer"/> for the update.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
protected abstract Task ExecuteInternal(IHandlerContainer container, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Telegrator.Handlers.Components;
|
||||
|
||||
namespace Telegrator.Handlers
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a handler container for a specific update type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUpdate">The type of update handled by the container.</typeparam>
|
||||
public interface IAbstractHandlerContainer<TUpdate> : IHandlerContainer where TUpdate : class
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the actual update object of type <typeparamref name="TUpdate"/>.
|
||||
/// </summary>
|
||||
public TUpdate ActualUpdate { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegram.Bot.Types.ReplyMarkups;
|
||||
using Telegrator.Attributes;
|
||||
using Telegrator.Filters.Components;
|
||||
using Telegrator.Handlers.Components;
|
||||
|
||||
namespace Telegrator.Handlers
|
||||
{
|
||||
/// <summary>
|
||||
/// Attribute that marks a handler to process message updates.
|
||||
/// This handler will be triggered when users send messages in chats.
|
||||
/// </summary>
|
||||
/// <param name="concurrency">The maximum number of concurrent executions allowed (default: 0 for unlimited).</param>
|
||||
public class MessageHandlerAttribute(int concurrency = 0) : UpdateHandlerAttribute<MessageHandler>(UpdateType.Message, concurrency)
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if the update contains a valid message.
|
||||
/// </summary>
|
||||
/// <param name="context">The filter execution context containing the update.</param>
|
||||
/// <returns>True if the update contains a message; otherwise, false.</returns>
|
||||
public override bool CanPass(FilterExecutionContext<Update> context) => context.Input is { Message: { } };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract base class for handlers that process message updates.
|
||||
/// Provides convenient methods for sending replies and responses to messages.
|
||||
/// </summary>
|
||||
public abstract class MessageHandler() : AbstractUpdateHandler<Message>(UpdateType.Message)
|
||||
{
|
||||
/// <summary>
|
||||
/// Sends a reply message to the current message.
|
||||
/// </summary>
|
||||
/// <param name="text">The text of the message to send.</param>
|
||||
/// <param name="parseMode">The parse mode for the message text.</param>
|
||||
/// <param name="replyMarkup">The reply markup for the message.</param>
|
||||
/// <param name="linkPreviewOptions">Options for link preview generation.</param>
|
||||
/// <param name="messageThreadId">The thread ID for forum topics.</param>
|
||||
/// <param name="entities">The message entities to include.</param>
|
||||
/// <param name="disableNotification">Whether to disable notification for the message.</param>
|
||||
/// <param name="protectContent">Whether to protect the message content.</param>
|
||||
/// <param name="messageEffectId">The message effect ID.</param>
|
||||
/// <param name="businessConnectionId">The business connection ID.</param>
|
||||
/// <param name="allowPaidBroadcast">Whether to allow paid broadcast.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The sent message.</returns>
|
||||
protected async Task<Message> Reply(
|
||||
string text,
|
||||
ParseMode parseMode = ParseMode.None,
|
||||
ReplyMarkup? replyMarkup = null,
|
||||
LinkPreviewOptions? linkPreviewOptions = null,
|
||||
int? messageThreadId = null,
|
||||
IEnumerable<MessageEntity>? entities = null,
|
||||
bool disableNotification = false,
|
||||
bool protectContent = false,
|
||||
string? messageEffectId = null,
|
||||
string? businessConnectionId = null,
|
||||
bool allowPaidBroadcast = false,
|
||||
CancellationToken cancellationToken = default)
|
||||
=> await Client.SendMessage(
|
||||
Input.Chat, text, parseMode, Input,
|
||||
replyMarkup, linkPreviewOptions,
|
||||
messageThreadId, entities,
|
||||
disableNotification, protectContent,
|
||||
messageEffectId, businessConnectionId,
|
||||
allowPaidBroadcast, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a response message to the current chat.
|
||||
/// </summary>
|
||||
/// <param name="text">The text of the message to send.</param>
|
||||
/// <param name="parseMode">The parse mode for the message text.</param>
|
||||
/// <param name="replyParameters">The reply parameters for the message.</param>
|
||||
/// <param name="replyMarkup">The reply markup for the message.</param>
|
||||
/// <param name="linkPreviewOptions">Options for link preview generation.</param>
|
||||
/// <param name="messageThreadId">The thread ID for forum topics.</param>
|
||||
/// <param name="entities">The message entities to include.</param>
|
||||
/// <param name="disableNotification">Whether to disable notification for the message.</param>
|
||||
/// <param name="protectContent">Whether to protect the message content.</param>
|
||||
/// <param name="messageEffectId">The message effect ID.</param>
|
||||
/// <param name="businessConnectionId">The business connection ID.</param>
|
||||
/// <param name="allowPaidBroadcast">Whether to allow paid broadcast.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The sent message.</returns>
|
||||
protected async Task<Message> Responce(
|
||||
string text,
|
||||
ParseMode parseMode = ParseMode.None,
|
||||
ReplyParameters? replyParameters = null,
|
||||
ReplyMarkup? replyMarkup = null,
|
||||
LinkPreviewOptions? linkPreviewOptions = null,
|
||||
int? messageThreadId = null,
|
||||
IEnumerable<MessageEntity>? entities = null,
|
||||
bool disableNotification = false,
|
||||
bool protectContent = false,
|
||||
string? messageEffectId = null,
|
||||
string? businessConnectionId = null,
|
||||
bool allowPaidBroadcast = false,
|
||||
CancellationToken cancellationToken = default)
|
||||
=> await Client.SendMessage(
|
||||
Input.Chat, text, parseMode, replyParameters,
|
||||
replyMarkup, linkPreviewOptions,
|
||||
messageThreadId, entities,
|
||||
disableNotification, protectContent,
|
||||
messageEffectId, businessConnectionId,
|
||||
allowPaidBroadcast, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract base class for branching handlers that process message updates.
|
||||
/// Provides convenient methods for sending replies and responses to messages in branching scenarios.
|
||||
/// </summary>
|
||||
public abstract class BranchingMessageHandler() : BranchingUpdateHandler<Message>(UpdateType.Message)
|
||||
{
|
||||
/// <summary>
|
||||
/// Sends a reply message to the current message.
|
||||
/// </summary>
|
||||
/// <param name="text">The text of the message to send.</param>
|
||||
/// <param name="parseMode">The parse mode for the message text.</param>
|
||||
/// <param name="replyMarkup">The reply markup for the message.</param>
|
||||
/// <param name="linkPreviewOptions">Options for link preview generation.</param>
|
||||
/// <param name="messageThreadId">The thread ID for forum topics.</param>
|
||||
/// <param name="entities">The message entities to include.</param>
|
||||
/// <param name="disableNotification">Whether to disable notification for the message.</param>
|
||||
/// <param name="protectContent">Whether to protect the message content.</param>
|
||||
/// <param name="messageEffectId">The message effect ID.</param>
|
||||
/// <param name="businessConnectionId">The business connection ID.</param>
|
||||
/// <param name="allowPaidBroadcast">Whether to allow paid broadcast.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The sent message.</returns>
|
||||
protected async Task<Message> Reply(
|
||||
string text,
|
||||
ParseMode parseMode = ParseMode.None,
|
||||
ReplyMarkup? replyMarkup = null,
|
||||
LinkPreviewOptions? linkPreviewOptions = null,
|
||||
int? messageThreadId = null,
|
||||
IEnumerable<MessageEntity>? entities = null,
|
||||
bool disableNotification = false,
|
||||
bool protectContent = false,
|
||||
string? messageEffectId = null,
|
||||
string? businessConnectionId = null,
|
||||
bool allowPaidBroadcast = false,
|
||||
CancellationToken cancellationToken = default)
|
||||
=> await Client.SendMessage(
|
||||
Input.Chat, text, parseMode, Input,
|
||||
replyMarkup, linkPreviewOptions,
|
||||
messageThreadId, entities,
|
||||
disableNotification, protectContent,
|
||||
messageEffectId, businessConnectionId,
|
||||
allowPaidBroadcast, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a response message to the current chat.
|
||||
/// </summary>
|
||||
/// <param name="text">The text of the message to send.</param>
|
||||
/// <param name="parseMode">The parse mode for the message text.</param>
|
||||
/// <param name="replyParameters">The reply parameters for the message.</param>
|
||||
/// <param name="replyMarkup">The reply markup for the message.</param>
|
||||
/// <param name="linkPreviewOptions">Options for link preview generation.</param>
|
||||
/// <param name="messageThreadId">The thread ID for forum topics.</param>
|
||||
/// <param name="entities">The message entities to include.</param>
|
||||
/// <param name="disableNotification">Whether to disable notification for the message.</param>
|
||||
/// <param name="protectContent">Whether to protect the message content.</param>
|
||||
/// <param name="messageEffectId">The message effect ID.</param>
|
||||
/// <param name="businessConnectionId">The business connection ID.</param>
|
||||
/// <param name="allowPaidBroadcast">Whether to allow paid broadcast.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The sent message.</returns>
|
||||
protected async Task<Message> Responce(
|
||||
string text,
|
||||
ParseMode parseMode = ParseMode.None,
|
||||
ReplyParameters? replyParameters = null,
|
||||
ReplyMarkup? replyMarkup = null,
|
||||
LinkPreviewOptions? linkPreviewOptions = null,
|
||||
int? messageThreadId = null,
|
||||
IEnumerable<MessageEntity>? entities = null,
|
||||
bool disableNotification = false,
|
||||
bool protectContent = false,
|
||||
string? messageEffectId = null,
|
||||
string? businessConnectionId = null,
|
||||
bool allowPaidBroadcast = false,
|
||||
CancellationToken cancellationToken = default)
|
||||
=> await Client.SendMessage(
|
||||
Input.Chat, text, parseMode, replyParameters,
|
||||
replyMarkup, linkPreviewOptions,
|
||||
messageThreadId, entities,
|
||||
disableNotification, protectContent,
|
||||
messageEffectId, businessConnectionId,
|
||||
allowPaidBroadcast, cancellationToken);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user