This commit is contained in:
Artemy
2025-07-19 23:18:08 +07:00
parent f524a9f0b7
commit 272809d1d8
19 changed files with 340 additions and 34 deletions
+3 -2
View File
@@ -1,13 +1,14 @@
using Govor.ConsoleClient.Services;
using Govor.ConsoleClient.Services.Interfaces;
namespace Govor.ConsoleClient;
public class App
{
private readonly InputPipeline _inputPipeline;
private readonly IInputPipeline _inputPipeline;
private readonly ILogger _logger;
public App(InputPipeline inputPipeline, ILogger logger)
public App(IInputPipeline inputPipeline, ILogger logger)
{
_logger = logger;
_inputPipeline = inputPipeline;
+46 -10
View File
@@ -1,22 +1,58 @@
using System.Reflection;
using Govor.ConsoleClient.Services;
using Govor.ConsoleClient.Services.Interfaces;
using Microsoft.Extensions.DependencyInjection;
namespace Govor.ConsoleClient.Commands;
public class HelpCommand : ICommand
{
private readonly IServiceProvider _serviceProvider;
private readonly ILogger _logger;
public HelpCommand(IServiceProvider serviceProvider, ILogger logger)
{
_serviceProvider = serviceProvider;
_logger = logger;
}
public Task ExecuteAsync(CommandContext context)
{
Console.WriteLine("Commands:");
var dispatcher = _serviceProvider.GetRequiredService<ICommandDispatcher>();
var commands = dispatcher.GetAllCommands();
if (context.Arguments is not null)
{
var command = commands.FirstOrDefault(c =>
(c.GetType().GetCustomAttribute<CommandRouteAttribute>()?.Path.Replace("/", "").ToLower()
?? c.GetType().Name.Replace("Command", "").ToLower()) == context.Arguments.ToLower());
if (command != null)
{
_logger.Info($"{context.Arguments} - {command.LongHelp()}");
}
else
{
_logger.Warn("Unknown command");
}
}
else
{
_logger.Info("Чтобы получить подробную информацию, напишите /help {command}");
}
foreach (var command in commands)
{
var name = command.GetType().GetCustomAttribute<CommandRouteAttribute>()?.Path.Replace("/", "").ToLower()
?? command.GetType().Name.Replace("Command", "").ToLower();
_logger.Log($"{name} - {command.ShortHelp()}");
}
return Task.CompletedTask;
}
public string LongHelp()
{
throw new NotImplementedException();
}
public string LongHelp() => "Необходима для получения информации о доступных командах\nЧтобы получить подробную информацию о команде, напишите /help {command}";
public string ShortHelp()
{
throw new NotImplementedException();
}
}
public string ShortHelp() => "Необходима для получения информации о доступных командах";
}
@@ -39,6 +39,6 @@ public class SendMessageCommand : IInteractiveCommand
public string ShortHelp()
{
throw new NotImplementedException();
return "Отпарвка тестовых сообщений не существующему юзеру";
}
}
+4 -5
View File
@@ -1,6 +1,8 @@
using System.Reflection;
using Govor.ConsoleClient.Commands;
using Govor.ConsoleClient.Services;
using Govor.ConsoleClient.Services.Extensions;
using Govor.ConsoleClient.Services.Interfaces;
using Govor.ConsoleClient.Services.Middleware;
using Microsoft.Extensions.DependencyInjection;
@@ -16,12 +18,9 @@ public static class DependencyInjection
services.AddCommands();
// Сервисы
services.AddSingleton<CommandDispatcher>();
services.AddSingleton<InputPipeline>();
services.AddSingleton<ConsoleLogger>();
services.AddSingleton<ILogger>(sp => sp.GetRequiredService<ConsoleLogger>());
services.AddApplicationServices();
services.AddSingleton<CommandContext>();
services.AddSingleton<MiddlewarePipeline>();
// Middleware
services.AddSingleton<ICommandMiddleware, ExceptionHandlingMiddleware>();
@@ -0,0 +1,18 @@
using Govor.ConsoleClient.Services.Implementations;
using Govor.ConsoleClient.Services.Interfaces;
using Microsoft.Extensions.DependencyInjection;
namespace Govor.ConsoleClient.Services.Extensions;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddApplicationServices(this IServiceCollection services)
{
services.AddSingleton<IInputPipeline, InputPipeline>();
services.AddSingleton<ICommandDispatcher, CommandDispatcher>();
services.AddSingleton<IMiddlewarePipeline, MiddlewarePipeline>();
services.AddSingleton<ConsoleLogger>();
services.AddSingleton<ILogger>(sp => sp.GetRequiredService<ConsoleLogger>());
return services;
}
}
@@ -1,15 +1,16 @@
using System.Reflection;
using Govor.ConsoleClient.Commands;
using Govor.ConsoleClient.Services.Interfaces;
namespace Govor.ConsoleClient.Services;
namespace Govor.ConsoleClient.Services.Implementations;
public class CommandDispatcher
public class CommandDispatcher : ICommandDispatcher
{
private readonly Dictionary<string, ICommand> _commands = new();
private readonly ILogger _logger;
private readonly MiddlewarePipeline _pipeline;
private readonly IMiddlewarePipeline _pipeline;
public CommandDispatcher(IEnumerable<ICommand> commands, ILogger logger, MiddlewarePipeline pipeline)
public CommandDispatcher(IEnumerable<ICommand> commands, ILogger logger, IMiddlewarePipeline pipeline)
{
_logger = logger;
_pipeline = pipeline;
@@ -38,4 +39,6 @@ public class CommandDispatcher
return null;
}
}
public IEnumerable<ICommand> GetAllCommands() => _commands.Values;
}
@@ -1,4 +1,6 @@
namespace Govor.ConsoleClient.Services;
using Govor.ConsoleClient.Services.Interfaces;
namespace Govor.ConsoleClient.Services.Implementations;
public class ConsoleLogger : ILogger
{
@@ -1,14 +1,15 @@
using Govor.ConsoleClient.Commands;
using Govor.ConsoleClient.Services.Interfaces;
namespace Govor.ConsoleClient.Services;
namespace Govor.ConsoleClient.Services.Implementations;
public class InputPipeline
public class InputPipeline : IInputPipeline
{
private readonly CommandDispatcher _dispatcher;
private readonly ICommandDispatcher _dispatcher;
private readonly ILogger _logger;
private IInteractiveCommand? _activeCommand;
public InputPipeline(CommandDispatcher dispatcher, ILogger logger)
public InputPipeline(ICommandDispatcher dispatcher, ILogger logger)
{
_dispatcher = dispatcher;
_logger = logger;
@@ -20,12 +21,12 @@ public class InputPipeline
if (input.StartsWith("/"))
{
_activeCommand = null; // Сброс активной команды
_activeCommand = null;
var commandInput = input[1..];
var result = await _dispatcher.DispatchAsync(commandInput);
// Если команда поддерживает интерактивность, сохраняем как активную
// If the command supports interactivity, save it as active
if (result is IInteractiveCommand interactiveCommand && !interactiveCommand.IsCompleted)
{
_activeCommand = interactiveCommand;
@@ -42,7 +43,7 @@ public class InputPipeline
}
else
{
_logger.Info($"[Ввод пользователя]: {input}");
_logger.Info($"Введите /help, чтобы узнать доступные команды!");
}
}
}
@@ -1,10 +1,11 @@
using Govor.ConsoleClient.Services.Interfaces;
using Govor.ConsoleClient.Services.Middleware;
namespace Govor.ConsoleClient.Services;
namespace Govor.ConsoleClient.Services.Implementations;
public delegate Task CommandMiddleware(CommandContext context, Func<Task> next);
public class MiddlewarePipeline
public class MiddlewarePipeline : IMiddlewarePipeline
{
private readonly IList<ICommandMiddleware> _middlewares;
@@ -0,0 +1,9 @@
using Govor.ConsoleClient.Commands;
namespace Govor.ConsoleClient.Services.Interfaces;
public interface ICommandDispatcher
{
Task<ICommand?> DispatchAsync(string input);
IEnumerable<ICommand> GetAllCommands();
}
@@ -0,0 +1,6 @@
namespace Govor.ConsoleClient.Services.Interfaces;
public interface IInputPipeline
{
Task ProcessInputAsync(string input);
}
@@ -1,4 +1,4 @@
namespace Govor.ConsoleClient.Services;
namespace Govor.ConsoleClient.Services.Interfaces;
public interface ILogger
{
@@ -0,0 +1,6 @@
namespace Govor.ConsoleClient.Services.Interfaces;
public interface IMiddlewarePipeline
{
Task ExecuteAsync(CommandContext context);
}
@@ -1,3 +1,5 @@
using Govor.ConsoleClient.Services.Interfaces;
namespace Govor.ConsoleClient.Services.Middleware;
public class ExceptionHandlingMiddleware : ICommandMiddleware
@@ -17,7 +19,7 @@ public class ExceptionHandlingMiddleware : ICommandMiddleware
}
catch (Exception ex)
{
_logger.Error($"Произошла ошибка при выполнении команды '{context.Route}': {ex.Message}");
_logger.Error($"Произошла ошибка при выполнении команды '{context?.Route}': {ex.Message}");
}
}
}
+3
View File
@@ -0,0 +1,3 @@
{
"BaseUrl": "https://govor-team-govor-88b3.twc1.net"
}