* Version incremented
* Added ability to handle errors during filters validation inside Handlers * Moved Result class to root directory * Added FilterOrigin enum
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<Version>1.0.10</Version>
|
||||
<Version>1.0.11</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<Version>1.0.10</Version>
|
||||
<Version>1.0.11</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Telegrator.Handlers;
|
||||
using Telegrator.Handlers.Components;
|
||||
using Telegrator.Handlers.Components;
|
||||
|
||||
namespace Telegrator.Aspects
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Telegrator.Handlers;
|
||||
using Telegrator.Handlers.Components;
|
||||
using Telegrator.Handlers.Components;
|
||||
|
||||
namespace Telegrator.Aspects
|
||||
{
|
||||
|
||||
@@ -70,6 +70,33 @@
|
||||
Sender
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Messages from where this filter was originated
|
||||
/// </summary>
|
||||
public enum FilterOrigin
|
||||
{
|
||||
/// <summary>
|
||||
/// None, empty filter
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// From <see cref="Attributes.UpdateHandlerAttribute{T}"/> update validator filter
|
||||
/// </summary>
|
||||
Validator,
|
||||
|
||||
/// <summary>
|
||||
/// From <see cref="Attributes.StateKeeperAttribute{TKey, TState, TKeeper}"/> state machine filter
|
||||
/// </summary>
|
||||
StateKeeper,
|
||||
|
||||
/// <summary>
|
||||
/// From regular <see cref="Attributes.UpdateFilterAttribute{T}"/>
|
||||
/// </summary>
|
||||
Regualr
|
||||
}
|
||||
|
||||
/*
|
||||
/// <summary>
|
||||
/// Levels of debug writing
|
||||
/// </summary>
|
||||
@@ -101,4 +128,5 @@
|
||||
/// </summary>
|
||||
HandlersPool = 0x8
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
using System.ComponentModel;
|
||||
using System.Threading;
|
||||
using Telegram.Bot.Polling;
|
||||
using Telegram.Bot.Polling;
|
||||
using Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegrator.MadiatorCore;
|
||||
using Telegrator.Filters.Components;
|
||||
using Telegrator.MadiatorCore.Descriptors;
|
||||
using Telegrator.Polling;
|
||||
|
||||
namespace Telegrator.Handlers.Components
|
||||
{
|
||||
@@ -102,5 +100,20 @@ namespace Telegrator.Handlers.Components
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
protected abstract Task<Result> ExecuteInternal(IHandlerContainer container, CancellationToken cancellationToken);
|
||||
|
||||
/// <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.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="failedFilter"></param>
|
||||
/// <param name="origin"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<Result> FiltersFallback(FilterExecutionContext<Update> context, IFilter<Update> failedFilter, FilterOrigin origin)
|
||||
{
|
||||
return Task.FromResult(Result.Ok());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
namespace Telegrator.Handlers
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents handler results, allowing to communicate with router and control aspect execution
|
||||
/// </summary>
|
||||
public sealed class Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Is result positive
|
||||
/// </summary>
|
||||
public bool Positive { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Should router search for next matching handler
|
||||
/// </summary>
|
||||
public bool RouteNext { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Exact type that router should search
|
||||
/// </summary>
|
||||
public Type? NextType { get; }
|
||||
|
||||
internal Result(bool positive, bool routeNext, Type? nextType)
|
||||
{
|
||||
Positive = positive;
|
||||
RouteNext = routeNext;
|
||||
NextType = nextType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// "OK" result
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Result Ok()
|
||||
=> new Result(true, false, null);
|
||||
|
||||
/// <summary>
|
||||
/// "Somethong went wrong" result
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Result Fault()
|
||||
=> new Result(false, false, null);
|
||||
|
||||
/// <summary>
|
||||
/// "Search next handler" result
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Result Next()
|
||||
=> new Result(true, true, null);
|
||||
|
||||
/// <summary>
|
||||
/// "Search next handler of type" result
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static Result Next<T>()
|
||||
=> new Result(true, true, typeof(T));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Telegrator.Aspects;
|
||||
using Telegrator.Handlers;
|
||||
using Telegrator.Handlers.Components;
|
||||
|
||||
namespace Telegrator.MadiatorCore.Descriptors
|
||||
|
||||
@@ -41,14 +41,18 @@ namespace Telegrator.MadiatorCore.Descriptors
|
||||
/// Validates the filter context using all filters in the set.
|
||||
/// </summary>
|
||||
/// <param name="filterContext">The filter execution context.</param>
|
||||
/// <param name="failedFilter"></param>
|
||||
/// <param name="origin"></param>
|
||||
/// <returns>True if all filters pass; otherwise, false.</returns>
|
||||
public bool Validate(FilterExecutionContext<Update> filterContext)
|
||||
public bool Validate(FilterExecutionContext<Update> filterContext, out IFilter<Update> failedFilter, out FilterOrigin origin)
|
||||
{
|
||||
if (UpdateValidator != null)
|
||||
{
|
||||
if (!UpdateValidator.CanPass(filterContext))
|
||||
{
|
||||
Alligator.LogDebug("(E) UpdateValidator filter of {0} for Update ({1}) didnt pass!", filterContext.Data["handler_name"], filterContext.Update.Id);
|
||||
failedFilter = UpdateValidator;
|
||||
origin = FilterOrigin.Validator;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -61,6 +65,8 @@ namespace Telegrator.MadiatorCore.Descriptors
|
||||
if (!StateKeeperValidator.CanPass(filterContext))
|
||||
{
|
||||
Alligator.LogDebug("(E) StateKeeperValidator filter of {0} for Update ({1}) didnt pass!", filterContext.Data["handler_name"], filterContext.Update.Id);
|
||||
failedFilter = StateKeeperValidator;
|
||||
origin = FilterOrigin.StateKeeper;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -77,6 +83,8 @@ namespace Telegrator.MadiatorCore.Descriptors
|
||||
if (filter is not AnonymousCompiledFilter && filter is not AnonymousTypeFilter)
|
||||
Alligator.LogDebug("(E) {0} filter of {1} for Update ({2}) didnt pass!", filter.GetType().Name, filterContext.Data["handler_name"], filterContext.Update.Id);
|
||||
|
||||
failedFilter = filter;
|
||||
origin = FilterOrigin.Regualr;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -85,6 +93,8 @@ namespace Telegrator.MadiatorCore.Descriptors
|
||||
}
|
||||
}
|
||||
|
||||
failedFilter = null!;
|
||||
origin = FilterOrigin.None;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Telegrator.Handlers;
|
||||
using Telegrator.Logging;
|
||||
using Telegrator.Logging;
|
||||
using Telegrator.MadiatorCore;
|
||||
using Telegrator.MadiatorCore.Descriptors;
|
||||
|
||||
|
||||
@@ -215,11 +215,18 @@ namespace Telegrator.Polling
|
||||
{ "handler_name", descriptor.ToString() }
|
||||
};
|
||||
|
||||
FilterExecutionContext<Update> filterContext = new FilterExecutionContext<Update>(_botInfo, update, update, data, []);
|
||||
if (descriptor.Filters != null && !descriptor.Filters.Validate(filterContext))
|
||||
return null;
|
||||
|
||||
UpdateHandlerBase handlerInstance = provider.GetHandlerInstance(descriptor, cancellationToken);
|
||||
|
||||
FilterExecutionContext<Update> filterContext = new FilterExecutionContext<Update>(_botInfo, update, update, data, []);
|
||||
if (descriptor.Filters != null && !descriptor.Filters.Validate(filterContext, out IFilter<Update> failedFilter, out FilterOrigin origin))
|
||||
{
|
||||
Result fallbackResult = handlerInstance.FiltersFallback(filterContext, failedFilter, origin).Result;
|
||||
if (!fallbackResult.Positive)
|
||||
throw new BreakDescribingException();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return new DescribedHandlerInfo(descriptor, this, AwaitingProvider, client, handlerInstance, filterContext, descriptor.DisplayString);
|
||||
}
|
||||
|
||||
@@ -266,5 +273,7 @@ namespace Telegrator.Polling
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class BreakDescribingException : Exception { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
using Telegram.Bot.Types;
|
||||
using Telegrator.Aspects;
|
||||
using Telegrator.Handlers.Components;
|
||||
using Telegrator.Filters.Components;
|
||||
using Telegrator.MadiatorCore;
|
||||
|
||||
namespace Telegrator
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents handler results, allowing to communicate with router and control aspect execution
|
||||
/// </summary>
|
||||
public sealed class Result
|
||||
{
|
||||
/// <summary>
|
||||
/// Is result positive
|
||||
/// </summary>
|
||||
public bool Positive { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Should router search for next matching handler
|
||||
/// </summary>
|
||||
public bool RouteNext { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Exact type that router should search
|
||||
/// </summary>
|
||||
public Type? NextType { get; }
|
||||
|
||||
internal Result(bool positive, bool routeNext, Type? nextType)
|
||||
{
|
||||
Positive = positive;
|
||||
RouteNext = routeNext;
|
||||
NextType = nextType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents 'success'
|
||||
/// <list type="bullet">
|
||||
/// <item>Inside <see cref="IPreProcessor"/> - let handler's main block be executed</item>
|
||||
/// <item>Inside <see cref="UpdateHandlerBase.FiltersFallback(FilterExecutionContext{Update}, IFilter{Update}, FilterOrigin)"/> - let router continue describing</item>
|
||||
/// <item>Inside <see cref="UpdateHandlerBase.ExecuteInternal(IHandlerContainer, CancellationToken)"/> - tells <see cref="IUpdateRouter"/> that he can stop describing, as needed handler was found</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Result Ok()
|
||||
=> new Result(true, false, null);
|
||||
|
||||
/// <summary>
|
||||
/// Represents 'fault' or 'error'. Use cases:
|
||||
/// <list type="bullet">
|
||||
/// <item>Inside <see cref="IPreProcessor"/> - interupts execution of handler, main block and <see cref="IPostProcessor"/> wont be executed</item>
|
||||
/// <item>Inside <see cref="UpdateHandlerBase.FiltersFallback(FilterExecutionContext{Update}, IFilter{Update}, FilterOrigin)"/> - interupts router's describing sequence</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Result Fault()
|
||||
=> new Result(false, false, null);
|
||||
|
||||
/// <summary>
|
||||
/// Represents 'continue'. Use cases:
|
||||
/// <list type="bullet">
|
||||
/// <item>Inside <see cref="UpdateHandlerBase.ExecuteInternal(IHandlerContainer, CancellationToken)"/> - Tells <see cref="IUpdateRouter"/> to continue describing handlers</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Result Next()
|
||||
=> new Result(true, true, null);
|
||||
|
||||
/// <summary>
|
||||
/// Represents 'chain'. Use cases:
|
||||
/// <list type="bullet">
|
||||
/// <item>Inside <see cref="UpdateHandlerBase.ExecuteInternal(IHandlerContainer, CancellationToken)"/> - Tells <see cref="IUpdateRouter"/> to continue describing handlers and execute only handlers of exact type</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static Result Next<T>()
|
||||
=> new Result(true, true, typeof(T));
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
<EnableNETAnalyzers>True</EnableNETAnalyzers>
|
||||
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<Version>1.0.10</Version>
|
||||
<Version>1.0.11</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user