* Added "INamedFilter" to tagging filters. Required for fallbacking system

* AnonymousCompiledFilter now has undependent realization
* All internal filters now implement INamedFilter interface
* Added new static methods to "Filter" class
* Added Filters fallbacking system
* Added "FiltersFallback" method in "UpdatehandlerBase"
* Changed filters validating system to be able to report failed filters
* Added "FiltersFallbackReport" class
* Added "FormReport" Property to "UpdateHandlerAttributeBase"
* Version incremented
This commit is contained in:
2025-08-08 17:04:56 +04:00
parent e790f31495
commit bf66431089
21 changed files with 338 additions and 101 deletions
@@ -0,0 +1,66 @@
using Telegram.Bot;
using Telegram.Bot.Types;
using Telegrator.Attributes.Components;
using Telegrator.Filters.Components;
using Telegrator.MadiatorCore.Descriptors;
namespace Telegrator.Handlers.Components
{
public class FiltersFallbackReport(HandlerDescriptor descriptor, FilterExecutionContext<Update> context)
{
public HandlerDescriptor Descriptor { get; } = descriptor;
public FilterExecutionContext<Update> Context { get; } = context;
public FilterFallbackInfo? UpdateValidator { get; set; }
public FilterFallbackInfo? StateKeeperValidator { get; set; }
public List<FilterFallbackInfo> UpdateFilters { get; } = [];
/*
public FilterFallbackInfo OfType<T>(int index = 0) where T : IFilter<Update>
{
return UpdateFilters.Where(info => info.Failed is T).ElementAt(index);
}
public FilterFallbackInfo OfAttribute<T>(int index = 0) where T : UpdateFilterAttributeBase
{
return UpdateFilters.Where(info => info.Name == typeof(T).Name).ElementAt(index);
}
public FilterFallbackInfo OfName(string name, int index = 0)
{
return UpdateFilters.Where(info => info.Name == name).ElementAt(index);
}
*/
public bool ExceptAttribute<T>(int index = 0) where T : UpdateFilterAttributeBase
{
string name = typeof(T).Name;
IEnumerable<FilterFallbackInfo> failed = UpdateFilters.Where(info => info.Failed);
if (failed.Count() > 1)
return false;
return failed.SingleOrDefault()?.Name == name;
}
}
public class FilterFallbackInfo(string name, IFilter<Update> filter, bool failed, Exception? exception)
{
public string Name { get; } = name;
public IFilter<Update> Filter { get; } = filter;
public bool Failed { get; } = failed;
public Exception? Exception { get; } = exception;
}
public enum FallbackReason
{
NullTarget,
FailedFilter
}
}
@@ -0,0 +1,27 @@
namespace Telegrator.Handlers.Components
{
/// <summary>
/// Represents a token that tracks the lifetime of a handler instance.
/// </summary>
public class HandlerLifetimeToken
{
/// <summary>
/// Event triggered when the handler's lifetime has ended.
/// </summary>
public event Action<HandlerLifetimeToken>? OnLifetimeEnded;
/// <summary>
/// Gets a value indicating whether the handler's lifetime has ended.
/// </summary>
public bool IsEnded { get; private set; }
/// <summary>
/// Marks the handler's lifetime as ended and triggers the event.
/// </summary>
public void LifetimeEnded()
{
IsEnded = true;
OnLifetimeEnded?.Invoke(this);
}
}
}
@@ -1,4 +1,5 @@
using Telegram.Bot.Polling;
using Telegram.Bot;
using Telegram.Bot.Polling;
using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
using Telegrator.Filters.Components;
@@ -41,7 +42,10 @@ namespace Telegrator.Handlers.Components
// Executing pre processor
if (aspects != null)
{
Result? preResult = await aspects.ExecutePre(this, container, cancellationToken).ConfigureAwait(false);
Result? preResult = await aspects
.ExecutePre(this, container, cancellationToken)
.ConfigureAwait(false);
if (!preResult.Positive)
return preResult;
}
@@ -54,7 +58,10 @@ namespace Telegrator.Handlers.Components
// Executing post processor
if (aspects != null)
{
Result postResult = await aspects.ExecutePost(this, container, cancellationToken).ConfigureAwait(false);
Result postResult = await aspects
.ExecutePost(this, container, cancellationToken)
.ConfigureAwait(false);
if (!postResult.Positive)
return postResult;
}
@@ -82,7 +89,7 @@ namespace Telegrator.Handlers.Components
}
}
private IHandlerContainer GetContainer(DescribedHandlerInfo handlerInfo)
internal IHandlerContainer GetContainer(DescribedHandlerInfo handlerInfo)
{
if (this is IHandlerContainerFactory handlerDefainedContainerFactory)
return handlerDefainedContainerFactory.CreateContainer(handlerInfo);
@@ -114,14 +121,14 @@ namespace Telegrator.Handlers.Components
/// <summary>
/// Handles failed filters during handler describing.
/// Use <see cref="Result"/> to control how router should treat this fail.
/// <see cref="Result.Ok"/> to silently continue decribing.
/// <see cref="Result.Fault"/> to stop\break decribing sequence.
/// <see cref="Result.Next"/> to silently continue decribing.
/// <see cref="Result.Fault"/> to stop\break desribing sequence.
/// </summary>
/// <param name="context"></param>
/// <param name="failedFilter"></param>
/// <param name="origin"></param>
/// <param name="report"></param>
/// <param name="client"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual Task<Result> FiltersFallback(FilterExecutionContext<Update> context, IFilter<Update> failedFilter, FilterOrigin origin)
public virtual Task<Result> FiltersFallback(FiltersFallbackReport report, ITelegramBotClient client, CancellationToken cancellationToken = default)
{
return Task.FromResult(Result.Ok());
}