Добавьте файлы проекта.
This commit is contained in:
24
BotPages.Core/Pipeline/ErrorHandlingMiddleware.cs
Normal file
24
BotPages.Core/Pipeline/ErrorHandlingMiddleware.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace BotPages.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Middleware обработки ошибок для надёжности.
|
||||
/// </summary>
|
||||
public sealed class ErrorHandlingMiddleware : IUpdateMiddleware
|
||||
{
|
||||
/// <summary>
|
||||
/// Перехватывает исключения и отправляет сообщение об ошибке пользователю.
|
||||
/// </summary>
|
||||
public async Task InvokeAsync(UpdateContext ctx, Func<Task> next, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
{
|
||||
await next();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error: {ex}");
|
||||
await ctx.Client.SendTextAsync(ctx.Chat.Id, "Произошла ошибка. Попробуйте ещё раз. /start", null, ct);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
BotPages.Core/Pipeline/IRouter.cs
Normal file
13
BotPages.Core/Pipeline/IRouter.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace BotPages.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Маршрутизатор обновлений на страницы.
|
||||
/// </summary>
|
||||
public interface IRouter
|
||||
{
|
||||
/// <summary>
|
||||
/// Определяет текущую страницу и вызывает её обработчик.
|
||||
/// </summary>
|
||||
Task RouteAsync(UpdateContext ctx, CancellationToken ct);
|
||||
}
|
||||
}
|
||||
13
BotPages.Core/Pipeline/IUpdateMiddleware.cs
Normal file
13
BotPages.Core/Pipeline/IUpdateMiddleware.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace BotPages.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Middleware обработки входящих обновлений.
|
||||
/// </summary>
|
||||
public interface IUpdateMiddleware
|
||||
{
|
||||
/// <summary>
|
||||
/// Вызывает промежуточную логику, затем следующий обработчик или роутер.
|
||||
/// </summary>
|
||||
Task InvokeAsync(UpdateContext ctx, Func<Task> next, CancellationToken ct);
|
||||
}
|
||||
}
|
||||
17
BotPages.Core/Pipeline/LoggingMiddleware.cs
Normal file
17
BotPages.Core/Pipeline/LoggingMiddleware.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace BotPages.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Middleware логирования входящих обновлений.
|
||||
/// </summary>
|
||||
public sealed class LoggingMiddleware : IUpdateMiddleware
|
||||
{
|
||||
/// <summary>
|
||||
/// Логирует базовую информацию об обновлении и вызывает следующий этап.
|
||||
/// </summary>
|
||||
public async Task InvokeAsync(UpdateContext ctx, Func<Task> next, CancellationToken ct)
|
||||
{
|
||||
Console.WriteLine($"[{DateTime.UtcNow:O}] Update: chat={ctx.Chat.Id}, user={ctx.User.Id}, text={ctx.Text}");
|
||||
await next();
|
||||
}
|
||||
}
|
||||
}
|
||||
34
BotPages.Core/Pipeline/Pipeline.cs
Normal file
34
BotPages.Core/Pipeline/Pipeline.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
namespace BotPages.Core
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Конвейер выполнения middleware и роутера.
|
||||
/// </summary>
|
||||
public sealed class Pipeline
|
||||
{
|
||||
private readonly IReadOnlyList<IUpdateMiddleware> _middlewares;
|
||||
private readonly IRouter _router;
|
||||
|
||||
/// <summary>
|
||||
/// Создаёт конвейер обработки обновлений.
|
||||
/// </summary>
|
||||
public Pipeline(IEnumerable<IUpdateMiddleware> middlewares, IRouter router)
|
||||
{
|
||||
_middlewares = middlewares.ToList();
|
||||
_router = router;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Запускает выполнение конвейера для заданного контекста.
|
||||
/// </summary>
|
||||
public Task ExecuteAsync(UpdateContext ctx, CancellationToken ct)
|
||||
{
|
||||
var index = 0;
|
||||
Task Next() => (index < _middlewares.Count)
|
||||
? _middlewares[index++].InvokeAsync(ctx, Next, ct)
|
||||
: _router.RouteAsync(ctx, ct);
|
||||
|
||||
return Next();
|
||||
}
|
||||
}
|
||||
}
|
||||
45
BotPages.Core/Pipeline/Router.cs
Normal file
45
BotPages.Core/Pipeline/Router.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
namespace BotPages.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Простой роутер: команды верхнего уровня и делегирование текущей странице.
|
||||
/// </summary>
|
||||
public sealed class Router : IRouter
|
||||
{
|
||||
private readonly IPageRegistry _pages;
|
||||
|
||||
/// <summary>
|
||||
/// Создаёт роутер страниц.
|
||||
/// </summary>
|
||||
public Router(IPageRegistry pages) => _pages = pages;
|
||||
|
||||
/// <summary>
|
||||
/// Определяет текущую страницу и вызывает её обработчик.
|
||||
/// </summary>
|
||||
public async Task RouteAsync(UpdateContext ctx, CancellationToken ct)
|
||||
{
|
||||
var text = ctx.Text ?? string.Empty;
|
||||
|
||||
if (text.StartsWith("/start", StringComparison.Ordinal))
|
||||
{
|
||||
await ctx.Nav.ReplaceAsync(_pages.DefaultPage.Id, null, ctx, ct);
|
||||
return;
|
||||
}
|
||||
|
||||
var current = (await ctx.Nav.CurrentAsync(ctx, ct))?.PageId;
|
||||
if (current is not null)
|
||||
{
|
||||
var pr = await _pages.Get(current).HandleAsync(ctx, ct);
|
||||
await ctx.Nav.ApplyResultAsync(ctx, pr, ct);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
await ctx.Nav.ReplaceAsync(_pages.DefaultPage.Id, null, ctx, ct);
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO: Вынести в "дефолтный /start page"
|
||||
await ctx.Client.SendTextAsync(ctx.Chat.Id, "Не понимаю. Нажмите /start.", null, ct);
|
||||
}
|
||||
}
|
||||
}
|
||||
25
BotPages.Core/Pipeline/ThrottleMiddleware.cs
Normal file
25
BotPages.Core/Pipeline/ThrottleMiddleware.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace BotPages.Core
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Middleware троттлинга для ограничений нагрузки.
|
||||
/// </summary>
|
||||
public sealed class ThrottleMiddleware : IUpdateMiddleware
|
||||
{
|
||||
private readonly TimeSpan _delay;
|
||||
|
||||
/// <summary>
|
||||
/// Создаёт middleware троттлинга.
|
||||
/// </summary>
|
||||
public ThrottleMiddleware(TimeSpan delay) => _delay = delay;
|
||||
|
||||
/// <summary>
|
||||
/// Добавляет искусственную задержку перед продолжением обработки.
|
||||
/// </summary>
|
||||
public async Task InvokeAsync(UpdateContext ctx, Func<Task> next, CancellationToken ct)
|
||||
{
|
||||
await Task.Delay(_delay, ct);
|
||||
await next();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user