diff --git a/BotPages.Core/Routing/CommandsRegistry.cs b/BotPages.Core/Routing/CommandsRegistry.cs
index a63d43e..6006a83 100644
--- a/BotPages.Core/Routing/CommandsRegistry.cs
+++ b/BotPages.Core/Routing/CommandsRegistry.cs
@@ -49,12 +49,10 @@ internal sealed class CommandsRegistry
var match = cmd.Pattern.Match(command);
if (match.Success)
{
- // Собираем аргументы
+ // Собираем именованные группы (без числовых)
var args = cmd.Pattern.GetGroupNames()
- .Where(n => n != "0")
- .Select(n => new { n, v = match.Groups[n].Value })
- .Where(x => !string.IsNullOrEmpty(x.v))
- .ToDictionary(x => x.n, x => x.v);
+ .Where(n => !int.TryParse(n, out _))
+ .ToDictionary(n => n, n => match.Groups[n].Value);
task = cmd.Handler(ctx, args, ct);
return true;
@@ -64,14 +62,21 @@ internal sealed class CommandsRegistry
return false;
}
+ ///
+ /// Универсальный парсер шаблонов: /cmd {a} {b?} {c}
+ ///
private static Regex ToRegex(string template)
{
- // Простейшее преобразование шаблона: "/open {page} {id?}" -> Regex
var escaped = Regex.Escape(template)
.Replace("\\{", "{").Replace("\\}", "}");
- var pattern = "^" + escaped
- .Replace("{page}", "(?\\S+)")
- .Replace("{id?}", "(?\\S+)?") + "$";
+
+ var pattern = "^" + Regex.Replace(escaped, @"\{(\w+)(\?)?\}", m =>
+ {
+ var name = m.Groups[1].Value;
+ var optional = m.Groups[2].Success;
+ return optional ? $"(?<{name}>\\S+)?" : $"(?<{name}>\\S+)";
+ }) + "$";
+
return new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
}
diff --git a/Demo/Pages/DetailsPage.cs b/Demo/Pages/DetailsPage.cs
index ca7307c..e8559bd 100644
--- a/Demo/Pages/DetailsPage.cs
+++ b/Demo/Pages/DetailsPage.cs
@@ -1,5 +1,6 @@
using BotPages.Core;
using BotPages.Core.Messaging;
+using BotPages.Core.Routing;
namespace Demo.Pages;
@@ -7,20 +8,20 @@ namespace Demo.Pages;
/// Страница ввода деталей заявки.
/// Страница с параметрами и получением состояния.
///
-public sealed class DetailsPage : StatefullPage
+public sealed class DetailsPage : StatefullPage
{
[Statefull("Request")]
private Models.Request Request;
- public override Task OnEnter(PageContext ctx, DetailsArgs args, CancellationToken ct)
+ public override Task OnEnter(PageContext ctx, string args, CancellationToken ct)
{
Request = new()
{
- Title = args.Title,
+ Title = args,
};
return new MessageBuilder(ctx)
- .Text($"Заголовок: {args.Title}\nДобавьте детали или нажмите Далее.")
+ .Text($"Заголовок: {args}\nДобавьте детали или нажмите Далее.")
.Inline(new InlineButton("Далее", "next"), new InlineButton("Назад", "back"))
.Reply("Отмена")
.SendAsync(ct);
@@ -52,12 +53,15 @@ public sealed class DetailsPage : StatefullPage
await SaveState(ctx, ct);
await ctx.Navigation.GoToAsync(ctx, ct);
}
-}
-///
-/// Аргументы для страницы DetailsPage.
-///
-public sealed class DetailsArgs
-{
- public string Title { get; set; } = "";
+ internal static string Command => "/create_request {title}";
+ internal static string CommandDescription => "создание заявки /create_request {title";
+ internal static CommandHandler CommandHandler = async (ctx, args, ct) =>
+ {
+ string? title = "";
+ args?.TryGetValue("title", out title);
+
+ // Навигация на страницу по имени
+ await ctx.Navigation.GoToAsync(ctx, title ?? "", ct);
+ };
}
\ No newline at end of file
diff --git a/Demo/Pages/TitlePage.cs b/Demo/Pages/TitlePage.cs
index 3e843f1..f270e5d 100644
--- a/Demo/Pages/TitlePage.cs
+++ b/Demo/Pages/TitlePage.cs
@@ -1,6 +1,7 @@
using BotPages.Core;
using BotPages.Core.Abstractions;
using BotPages.Core.Messaging;
+using BotPages.Core.Routing;
namespace Demo.Pages;
///
@@ -23,7 +24,7 @@ public sealed class TitlePage : SingletonPage
}
else
{
- return ctx.Navigation.GoToAsync(ctx, new DetailsArgs { Title = text }, ct);
+ return ctx.Navigation.GoToAsync(ctx, text, ct);
}
}
}
\ No newline at end of file
diff --git a/Demo/Program.cs b/Demo/Program.cs
index 5cd2209..355fa7d 100644
--- a/Demo/Program.cs
+++ b/Demo/Program.cs
@@ -38,6 +38,7 @@ namespace Demo
.AddDefaultPage()
.MapCommand("/start", true, "Главная")
.MapCommand("/open {page}", openHandler, true, "открыть станицу /open {page}")
+ .MapCommand(DetailsPage.Command, DetailsPage.CommandHandler, true, DetailsPage.CommandDescription)
.AutoMapRoute()
.AddMiddleware(new ErrorHandlingMiddleware(logger))
.AddMiddleware(new LoggingMiddleware(logger))