diff --git a/Telegrator.sln b/Telegrator.sln
index 88c8e42..f9bed94 100644
--- a/Telegrator.sln
+++ b/Telegrator.sln
@@ -20,8 +20,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Telegrator.Analyzers", "Tel
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Telegrator.Hosting.Web", "Telegrator.Hosting.Web\Telegrator.Hosting.Web.csproj", "{98AB490F-6A36-CCFF-F6E6-B029D1665965}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SosalBot", "..\SosalBot\SosalBot\SosalBot.csproj", "{D6AA4D47-0DCE-520E-5779-A14EA9CB1DEC}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
AnalyzersDebug|Any CPU = AnalyzersDebug|Any CPU
@@ -65,12 +63,6 @@ Global
{98AB490F-6A36-CCFF-F6E6-B029D1665965}.Debug|Any CPU.Build.0 = Debug|Any CPU
{98AB490F-6A36-CCFF-F6E6-B029D1665965}.Release|Any CPU.ActiveCfg = Release|Any CPU
{98AB490F-6A36-CCFF-F6E6-B029D1665965}.Release|Any CPU.Build.0 = Release|Any CPU
- {D6AA4D47-0DCE-520E-5779-A14EA9CB1DEC}.AnalyzersDebug|Any CPU.ActiveCfg = Release|Any CPU
- {D6AA4D47-0DCE-520E-5779-A14EA9CB1DEC}.AnalyzersDebug|Any CPU.Build.0 = Release|Any CPU
- {D6AA4D47-0DCE-520E-5779-A14EA9CB1DEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {D6AA4D47-0DCE-520E-5779-A14EA9CB1DEC}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {D6AA4D47-0DCE-520E-5779-A14EA9CB1DEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {D6AA4D47-0DCE-520E-5779-A14EA9CB1DEC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Telegrator/Annotations/CommandAlliasAttribute.cs b/Telegrator/Annotations/CommandAlliasAttribute.cs
index 98db005..6766028 100644
--- a/Telegrator/Annotations/CommandAlliasAttribute.cs
+++ b/Telegrator/Annotations/CommandAlliasAttribute.cs
@@ -47,7 +47,8 @@ namespace Telegrator.Annotations
///
/// The command aliases to match against.
public CommandAlliasAttribute(params string[] alliases)
- : base(new CommandAlliasFilter(alliases)) => Alliases = alliases.Select(c => c.TrimStart('/')).ToArray();
+ : base(new CommandAlliasFilter(alliases.Select(c => c.TrimStart('/')).ToArray()))
+ => Alliases = alliases.Select(c => c.TrimStart('/')).ToArray();
///
/// Gets the filtering target (Message) from the update.
diff --git a/Telegrator/Annotations/CommandArgumentAttributes.cs b/Telegrator/Annotations/CommandArgumentAttributes.cs
new file mode 100644
index 0000000..a38f797
--- /dev/null
+++ b/Telegrator/Annotations/CommandArgumentAttributes.cs
@@ -0,0 +1,25 @@
+using System.Text.RegularExpressions;
+using Telegrator.Filters;
+
+namespace Telegrator.Annotations
+{
+ public class ArgumentStartsWithAttribute(string content, StringComparison comparison = StringComparison.InvariantCulture, int index = 0)
+ : MessageFilterAttribute(new ArgumentStartsWithFilter(content, comparison, index))
+ { }
+
+ public class ArgumentEndsWithAttribute(string content, StringComparison comparison = StringComparison.InvariantCulture, int index = 0)
+ : MessageFilterAttribute(new ArgumentEndsWithFilter(content, comparison, index))
+ { }
+
+ public class ArgumentContainsAttribute(string content, StringComparison comparison = StringComparison.InvariantCulture, int index = 0)
+ : MessageFilterAttribute(new ArgumentContainsFilter(content, comparison, index))
+ { }
+
+ public class ArgumentEqualsAttribute(string content, StringComparison comparison = StringComparison.InvariantCulture, int index = 0)
+ : MessageFilterAttribute(new ArgumentEqualsFilter(content, comparison, index))
+ { }
+
+ public class ArgumentRegexAttribute(string pattern, RegexOptions options = RegexOptions.None, TimeSpan matchTimeout = default, int index = 0)
+ : MessageFilterAttribute(new ArgumentRegexFilter(pattern, options, matchTimeout, index))
+ { }
+}
diff --git a/Telegrator/Filters/CommandArgumentFilter.cs b/Telegrator/Filters/CommandArgumentFilter.cs
index 57924a5..1274e6a 100644
--- a/Telegrator/Filters/CommandArgumentFilter.cs
+++ b/Telegrator/Filters/CommandArgumentFilter.cs
@@ -1,20 +1,81 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
+using System.Text.RegularExpressions;
using Telegram.Bot.Types;
using Telegrator.Filters.Components;
using Telegrator.Handlers;
namespace Telegrator.Filters
{
- public class CommandArgumentFilter : Filter
+ public abstract class CommandArgumentFilterBase(int index) : Filter
{
+ protected string Target { get; private set; } = null!;
+
public override bool CanPass(FilterExecutionContext context)
{
CommandHandlerAttribute attr = context.CompletedFilters.Get(0);
string[] args = attr.Arguments ??= context.Input.SplitArgs();
+ Target = args.ElementAtOrDefault(index);
- return alliases.Contains(ReceivedCommand, StringComparer.InvariantCultureIgnoreCase);
+ if (Target == null)
+ return false;
+
+ return CanPassNext(context);
+ }
+
+ protected abstract bool CanPassNext(FilterExecutionContext context);
+ }
+
+ public class ArgumentStartsWithFilter(string content, StringComparison comparison = StringComparison.InvariantCulture, int index = 0) : CommandArgumentFilterBase(index)
+ {
+ protected readonly string Content = content;
+ protected readonly StringComparison Comparison = comparison;
+
+ protected override bool CanPassNext(FilterExecutionContext _)
+ => Target.StartsWith(Content, Comparison);
+ }
+
+ public class ArgumentEndsWithFilter(string content, StringComparison comparison = StringComparison.InvariantCulture, int index = 0) : CommandArgumentFilterBase(index)
+ {
+ protected readonly string Content = content;
+ protected readonly StringComparison Comparison = comparison;
+
+ protected override bool CanPassNext(FilterExecutionContext _)
+ => Target.EndsWith(Content, Comparison);
+ }
+
+ public class ArgumentContainsFilter(string content, StringComparison comparison = StringComparison.InvariantCulture, int index = 0) : CommandArgumentFilterBase(index)
+ {
+ protected readonly string Content = content;
+ protected readonly StringComparison Comparison = comparison;
+
+ protected override bool CanPassNext(FilterExecutionContext _)
+ => Target.IndexOf(Content, Comparison) >= 0;
+ }
+
+ public class ArgumentEqualsFilter(string content, StringComparison comparison = StringComparison.InvariantCulture, int index = 0) : CommandArgumentFilterBase(index)
+ {
+ protected readonly string Content = content;
+ protected readonly StringComparison Comparison = comparison;
+
+ protected override bool CanPassNext(FilterExecutionContext _)
+ => Target.Equals(Content, Comparison);
+ }
+
+ public class ArgumentRegexFilter : CommandArgumentFilterBase
+ {
+ private readonly Regex _regex;
+
+ public Match Match { get; private set; } = null!;
+
+ public ArgumentRegexFilter(Regex regex, int index = 0)
+ : base(index) => _regex = regex;
+
+ public ArgumentRegexFilter(string pattern, RegexOptions options = RegexOptions.None, TimeSpan matchTimeout = default, int index = 0)
+ : base(index) => _regex = new Regex(pattern, options, matchTimeout);
+
+ protected override bool CanPassNext(FilterExecutionContext context)
+ {
+ Match = _regex.Match(Target);
+ return Match.Success;
}
}
}
diff --git a/Telegrator/Handlers/Components/BranchingUpdateHandler.cs b/Telegrator/Handlers/Components/BranchingUpdateHandler.cs
index 279488f..338627c 100644
--- a/Telegrator/Handlers/Components/BranchingUpdateHandler.cs
+++ b/Telegrator/Handlers/Components/BranchingUpdateHandler.cs
@@ -29,7 +29,7 @@ namespace Telegrator.Handlers.Components
///
/// Gets the allowed return types for branch methods.
///
- protected virtual Type[] AllowedBranchReturnTypes => [typeof(void), typeof(Task)];
+ protected virtual Type[] AllowedBranchReturnTypes => [typeof(void), typeof(Task)];
///
/// Gets the cancellation token for the current execution.
@@ -75,10 +75,10 @@ namespace Telegrator.Handlers.Components
Type thisType = GetType();
if (branch.GetParameters().Length != 0)
- throw new Exception();
+ throw new Exception("Branch method must have no parameters.");
if (!AllowedBranchReturnTypes.Any(branch.ReturnType.Equals))
- throw new Exception();
+ throw new Exception("Branch method must have one of allowed return types. [void, Task]");
try
{
diff --git a/Telegrator/MadiatorCore/Descriptors/DescriptorFiltersSet.cs b/Telegrator/MadiatorCore/Descriptors/DescriptorFiltersSet.cs
index f6e20e6..ec2aacc 100644
--- a/Telegrator/MadiatorCore/Descriptors/DescriptorFiltersSet.cs
+++ b/Telegrator/MadiatorCore/Descriptors/DescriptorFiltersSet.cs
@@ -1,5 +1,4 @@
using Telegram.Bot.Types;
-using Telegrator.Filters;
using Telegrator.Filters.Components;
using Telegrator.Handlers.Components;
using Telegrator.Logging;
diff --git a/Telegrator/Result.cs b/Telegrator/Result.cs
index ac745fb..98d9be1 100644
--- a/Telegrator/Result.cs
+++ b/Telegrator/Result.cs
@@ -38,6 +38,7 @@ namespace Telegrator
///
/// - Inside - let handler's main block be executed
/// - Inside - tells that he can stop describing, as needed handler was found
+ /// - Inside - let continue describing
///
///
///
@@ -58,7 +59,7 @@ namespace Telegrator
///
/// Represents 'continue'. Use cases:
///
- /// - Inside - let router continue describing
+ /// - Inside - let continue describing
/// - Inside - Tells to continue describing handlers
///
///