mirror of
https://github.com/Govor-team/Govor.git
synced 2026-07-21 11:44:56 +00:00
Refactor console client to new Govor.ConsoleClient project
Removed Govor.Console implementation and introduced a new Govor.ConsoleClient project with a modular command-based architecture. Added dependency injection, command dispatcher, middleware pipeline, logging, and interactive command support. Updated solution and project files to reflect the new structure.
This commit is contained in:
@@ -1,57 +0,0 @@
|
|||||||
using System.Net.Http.Json;
|
|
||||||
using Govor.Contracts.DTOs;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks; // Added for Task
|
|
||||||
|
|
||||||
namespace Govor.ConsoleClient
|
|
||||||
{
|
|
||||||
public class FriendsClient
|
|
||||||
{
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
|
|
||||||
public FriendsClient(HttpClient client)
|
|
||||||
{
|
|
||||||
_client = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<List<UserDto>> SearchAsync(string query)
|
|
||||||
{
|
|
||||||
var response = await _client.GetAsync($"/api/friends/search?query={query}");
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
return await response.Content.ReadFromJsonAsync<List<UserDto>>() ?? new List<UserDto>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendFriendRequestAsync was removed as the SendFriendRequestCommand now uses SignalR directly.
|
|
||||||
// public async Task SendFriendRequestAsync(Guid targetUserId)
|
|
||||||
// {
|
|
||||||
// var response = await _client.PostAsync($"api/friends/request?targetUserId={targetUserId}", null);
|
|
||||||
// response.EnsureSuccessStatusCode();
|
|
||||||
// }
|
|
||||||
|
|
||||||
public async Task<List<FriendshipDto>> GetIncomingRequestsAsync()
|
|
||||||
{
|
|
||||||
var response = await _client.GetAsync("/api/friends/requests");
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
return await response.Content.ReadFromJsonAsync<List<FriendshipDto>>() ?? new List<FriendshipDto>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// AcceptFriendRequestAsync was removed as the AcceptFriendRequestCommand now uses SignalR directly.
|
|
||||||
// public async Task AcceptFriendRequestAsync(Guid friendshipId) // Parameter was requesterId, should be friendshipId
|
|
||||||
// {
|
|
||||||
// var response = await _client.PostAsync($"/api/friends/accept?friendshipId={friendshipId}", null);
|
|
||||||
// response.EnsureSuccessStatusCode();
|
|
||||||
// }
|
|
||||||
|
|
||||||
public async Task<List<UserDto>> GetFriendsAsync()
|
|
||||||
{
|
|
||||||
var response = await _client.GetAsync("/api/friends");
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
return await response.Content.ReadFromJsonAsync<List<UserDto>>() ?? new List<UserDto>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.SignalR.Client;
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Govor.Contracts.Responses.SignalR;
|
|
||||||
|
|
||||||
namespace Govor.ConsoleClient;
|
|
||||||
|
|
||||||
|
|
||||||
public class FriendsHubClient
|
|
||||||
{
|
|
||||||
private readonly string _hubUrl;
|
|
||||||
private readonly string _jwtToken;
|
|
||||||
private HubConnection _connection;
|
|
||||||
|
|
||||||
public FriendsHubClient(string hubUrl, string jwtToken)
|
|
||||||
{
|
|
||||||
_hubUrl = hubUrl;
|
|
||||||
_jwtToken = jwtToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ConnectAsync()
|
|
||||||
{
|
|
||||||
_connection = new HubConnectionBuilder()
|
|
||||||
.WithUrl($"{_hubUrl}/friends", options =>
|
|
||||||
{
|
|
||||||
options.AccessTokenProvider = () => Task.FromResult(_jwtToken);
|
|
||||||
})
|
|
||||||
.WithAutomaticReconnect()
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
// Событие: получен входящий запрос в друзья
|
|
||||||
_connection.On<string>("FriendRequestReceived", userId =>
|
|
||||||
{
|
|
||||||
Console.WriteLine($"📨 Friend request received from: {userId}");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Событие: запрос принят
|
|
||||||
_connection.On<string>("FriendRequestAccepted", friendshipId =>
|
|
||||||
{
|
|
||||||
Console.WriteLine($"✅ Friend request accepted! Friendship ID: {friendshipId}");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Событие: запрос отклонён
|
|
||||||
_connection.On<string>("FriendRequestRejected", friendshipId =>
|
|
||||||
{
|
|
||||||
Console.WriteLine($"❌ Friend request rejected! Friendship ID: {friendshipId}");
|
|
||||||
});
|
|
||||||
|
|
||||||
await _connection.StartAsync();
|
|
||||||
Console.WriteLine("✅ Connected to FriendsHub");
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SendFriendRequestAsync(Guid targetUserId)
|
|
||||||
{
|
|
||||||
var result = await _connection.InvokeAsync<HubResult<object>>("SendRequest", targetUserId);
|
|
||||||
Console.WriteLine($"📤 Friend request sent. Status: {result.Status}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task AcceptFriendRequestAsync(Guid friendshipId)
|
|
||||||
{
|
|
||||||
var result = await _connection.InvokeAsync<HubResult<object>>("AcceptRequest", friendshipId);
|
|
||||||
Console.WriteLine($"👍 Accept result: {result.Status}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task RejectFriendRequestAsync(Guid friendshipId)
|
|
||||||
{
|
|
||||||
var result = await _connection.InvokeAsync<HubResult<object>>("RejectRequest", friendshipId);
|
|
||||||
Console.WriteLine($"👎 Reject result: {result.Status}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
using System.Net.Http;
|
|
||||||
using System.Net.Http.Json;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Govor.Contracts.Requests;
|
|
||||||
|
|
||||||
namespace Govor.ConsoleClient
|
|
||||||
{
|
|
||||||
public class HttpClientService
|
|
||||||
{
|
|
||||||
private readonly HttpClient _client;
|
|
||||||
|
|
||||||
public HttpClientService(string baseUrl)
|
|
||||||
{
|
|
||||||
_client = new HttpClient
|
|
||||||
{
|
|
||||||
BaseAddress = new Uri(baseUrl)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetBaseUrl() => _client.BaseAddress?.ToString() ?? string.Empty;
|
|
||||||
|
|
||||||
public async Task<string> GetAsync(string uri)
|
|
||||||
{
|
|
||||||
var response = await _client.GetAsync(uri);
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
return await response.Content.ReadAsStringAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<string> PostAsync(string uri, object? payload = null)
|
|
||||||
{
|
|
||||||
HttpResponseMessage response;
|
|
||||||
|
|
||||||
if (payload is null)
|
|
||||||
response = await _client.PostAsync(uri, null);
|
|
||||||
else
|
|
||||||
response = await _client.PostAsJsonAsync(uri, payload);
|
|
||||||
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
return await response.Content.ReadAsStringAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<string> RegisterAsync(string username, string password, string inviteCode)
|
|
||||||
{
|
|
||||||
var request = new RegistrationRequest
|
|
||||||
{
|
|
||||||
Name = username,
|
|
||||||
Password = password,
|
|
||||||
InviteLink = inviteCode
|
|
||||||
};
|
|
||||||
|
|
||||||
var response = await _client.PostAsJsonAsync("/api/auth/register", request);
|
|
||||||
if (response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
var result = await response.Content.ReadFromJsonAsync<TokenResponse>();
|
|
||||||
return result?.Token;
|
|
||||||
}
|
|
||||||
|
|
||||||
var error = await response.Content.ReadAsStringAsync();
|
|
||||||
throw new Exception($"Registration failed: {error}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<string> LoginAsync(string username, string password)
|
|
||||||
{
|
|
||||||
var request = new LoginRequest
|
|
||||||
{
|
|
||||||
Name = username,
|
|
||||||
Password = password
|
|
||||||
};
|
|
||||||
|
|
||||||
var response = await _client.PostAsJsonAsync("/api/auth/login", request);
|
|
||||||
if (response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
var result = await response.Content.ReadFromJsonAsync<TokenResponse>();
|
|
||||||
return result?.Token;
|
|
||||||
}
|
|
||||||
|
|
||||||
var error = await response.Content.ReadAsStringAsync();
|
|
||||||
throw new Exception($"Login failed: {error}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TokenResponse
|
|
||||||
{
|
|
||||||
public string Token { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
using Govor.ConsoleClient;
|
|
||||||
|
|
||||||
internal class Program
|
|
||||||
{
|
|
||||||
private const string HubBaseUrl = "https://govor-team-govor-88b3.twc1.net/hubs";
|
|
||||||
private static string jwtToken = "eyJhbGciOiJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNobWFjLXNoYTI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI4NDRjNzkyMi1hNjdlLTRlMzctYWI0MC0wNThlZDE5NzM5NjMiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiJBZG1pbiIsImV4cCI6MTc1MjQ4MzE0MH0.ECXLPwIljdeWgWUJtBiXXQXKMFC8Iw0x7_zdjbsUe1I"; // сюда подставьте валидный JWT
|
|
||||||
|
|
||||||
static async Task Main()
|
|
||||||
{
|
|
||||||
Console.Write("🔑 JWT Token: ");
|
|
||||||
jwtToken = Console.ReadLine();
|
|
||||||
|
|
||||||
var client = new FriendsHubClient(HubBaseUrl, jwtToken);
|
|
||||||
await client.ConnectAsync();
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
Console.WriteLine("\n1. Send friend request");
|
|
||||||
Console.WriteLine("2. Accept request");
|
|
||||||
Console.WriteLine("3. Reject request");
|
|
||||||
Console.Write("➡ Choose option: ");
|
|
||||||
var option = Console.ReadLine();
|
|
||||||
|
|
||||||
switch (option)
|
|
||||||
{
|
|
||||||
case "1":
|
|
||||||
Console.Write("Target UserId: ");
|
|
||||||
if (Guid.TryParse(Console.ReadLine(), out var targetId))
|
|
||||||
{
|
|
||||||
await client.SendFriendRequestAsync(targetId);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "2":
|
|
||||||
Console.Write("FriendshipId to accept: ");
|
|
||||||
if (Guid.TryParse(Console.ReadLine(), out var acceptId))
|
|
||||||
{
|
|
||||||
await client.AcceptFriendRequestAsync(acceptId);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "3":
|
|
||||||
Console.Write("FriendshipId to reject: ");
|
|
||||||
if (Guid.TryParse(Console.ReadLine(), out var rejectId))
|
|
||||||
{
|
|
||||||
await client.RejectFriendRequestAsync(rejectId);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Console.WriteLine("❗ Unknown option");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using Govor.ConsoleClient.Services;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient;
|
||||||
|
|
||||||
|
public class App
|
||||||
|
{
|
||||||
|
private readonly InputPipeline _inputPipeline;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
public App(InputPipeline inputPipeline, ILogger logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_inputPipeline = inputPipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RunAsync()
|
||||||
|
{
|
||||||
|
_logger.Title("Добро пожаловать в консольный клиент Говор!");
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
Console.Write(">> ");
|
||||||
|
var input = Console.ReadLine();
|
||||||
|
if (input == null || input.Trim().ToLower() == "exit") break;
|
||||||
|
await _inputPipeline.ProcessInputAsync(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using Govor.ConsoleClient.Services;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands;
|
||||||
|
|
||||||
|
public class HelpCommand : ICommand
|
||||||
|
{
|
||||||
|
public Task ExecuteAsync(CommandContext context)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Commands:");
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string LongHelp()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ShortHelp()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using Govor.ConsoleClient.Services;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands;
|
||||||
|
|
||||||
|
public interface ICommand
|
||||||
|
{
|
||||||
|
Task ExecuteAsync(CommandContext context);
|
||||||
|
string LongHelp();
|
||||||
|
string ShortHelp();
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class CommandRouteAttribute : Attribute
|
||||||
|
{
|
||||||
|
public string Path { get; }
|
||||||
|
public CommandRouteAttribute(string path) => Path = path;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Govor.ConsoleClient.Commands;
|
||||||
|
|
||||||
|
public interface IInteractiveCommand : ICommand
|
||||||
|
{
|
||||||
|
Task HandleInputAsync(string input);
|
||||||
|
bool IsCompleted { get; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using Govor.ConsoleClient.Services;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands;
|
||||||
|
|
||||||
|
[CommandRoute("/send")]
|
||||||
|
public class SendMessageCommand : IInteractiveCommand
|
||||||
|
{
|
||||||
|
private string? _recipient;
|
||||||
|
private bool _isCompleted;
|
||||||
|
public bool IsCompleted => _isCompleted;
|
||||||
|
|
||||||
|
public Task ExecuteAsync(CommandContext context)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Кому вы хотите отправить сообщение?");
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task HandleInputAsync(string input)
|
||||||
|
{
|
||||||
|
if (_recipient == null)
|
||||||
|
{
|
||||||
|
_recipient = input;
|
||||||
|
Console.WriteLine("Введите сообщение:");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var message = input;
|
||||||
|
Console.WriteLine($"(Отправка '{message}' пользователю '{_recipient}')");
|
||||||
|
_isCompleted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string LongHelp()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ShortHelp()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using Govor.ConsoleClient.Commands;
|
||||||
|
using Govor.ConsoleClient.Services;
|
||||||
|
using Govor.ConsoleClient.Services.Middleware;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient;
|
||||||
|
|
||||||
|
public static class DependencyInjection
|
||||||
|
{
|
||||||
|
public static IServiceProvider Configure()
|
||||||
|
{
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
|
||||||
|
// Регистрация команд
|
||||||
|
services.AddCommands();
|
||||||
|
|
||||||
|
// Сервисы
|
||||||
|
services.AddSingleton<CommandDispatcher>();
|
||||||
|
services.AddSingleton<InputPipeline>();
|
||||||
|
services.AddSingleton<ConsoleLogger>();
|
||||||
|
services.AddSingleton<ILogger>(sp => sp.GetRequiredService<ConsoleLogger>());
|
||||||
|
services.AddSingleton<CommandContext>();
|
||||||
|
services.AddSingleton<MiddlewarePipeline>();
|
||||||
|
|
||||||
|
// Middleware
|
||||||
|
services.AddSingleton<ICommandMiddleware, ExceptionHandlingMiddleware>();
|
||||||
|
|
||||||
|
|
||||||
|
return services.BuildServiceProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IServiceCollection AddCommands(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
var commandTypes = Assembly.GetExecutingAssembly()
|
||||||
|
.GetTypes()
|
||||||
|
.Where(t => typeof(ICommand).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract);
|
||||||
|
|
||||||
|
foreach (var type in commandTypes)
|
||||||
|
{
|
||||||
|
services.AddTransient(typeof(ICommand), type);
|
||||||
|
services.AddTransient(type); // Для прямого внедрения
|
||||||
|
}
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,5 +19,12 @@
|
|||||||
<ProjectReference Include="..\Govor.Core\Govor.Core.csproj" />
|
<ProjectReference Include="..\Govor.Core\Govor.Core.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Api\" />
|
||||||
|
<Folder Include="Commands\Auth\" />
|
||||||
|
<Folder Include="Models\" />
|
||||||
|
<Folder Include="Utils\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient;
|
||||||
|
|
||||||
|
internal class Program
|
||||||
|
{
|
||||||
|
//private const string HubBaseUrl = "https://govor-team-govor-88b3.twc1.net/hubs";
|
||||||
|
|
||||||
|
static async Task Main()
|
||||||
|
{
|
||||||
|
Console.Title = "Govor Console Client";
|
||||||
|
|
||||||
|
var serviceProvider = DependencyInjection.Configure();
|
||||||
|
|
||||||
|
var app = ActivatorUtilities.CreateInstance<App>(serviceProvider);
|
||||||
|
await app.RunAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using Govor.ConsoleClient.Commands;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Services;
|
||||||
|
|
||||||
|
public class CommandContext
|
||||||
|
{
|
||||||
|
public string Route { get; }
|
||||||
|
public string? Arguments { get; }
|
||||||
|
public ICommand Command { get; }
|
||||||
|
|
||||||
|
public CommandContext(string route, string? arguments, ICommand command)
|
||||||
|
{
|
||||||
|
Route = route;
|
||||||
|
Arguments = arguments;
|
||||||
|
Command = command;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using Govor.ConsoleClient.Commands;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Services;
|
||||||
|
|
||||||
|
public class CommandDispatcher
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, ICommand> _commands = new();
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
private readonly MiddlewarePipeline _pipeline;
|
||||||
|
|
||||||
|
public CommandDispatcher(IEnumerable<ICommand> commands, ILogger logger, MiddlewarePipeline pipeline)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_pipeline = pipeline;
|
||||||
|
|
||||||
|
foreach (var command in commands)
|
||||||
|
{
|
||||||
|
var route = command.GetType().GetCustomAttribute<CommandRouteAttribute>()?.Path.Replace("/","")
|
||||||
|
?? command.GetType().Name.Replace("Command", "").ToLower();
|
||||||
|
_commands[route.ToLower()] = command;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ICommand?> DispatchAsync(string input)
|
||||||
|
{
|
||||||
|
var args = input.Split(' ', 2);
|
||||||
|
var cmd = args[0].ToLower();
|
||||||
|
if (_commands.TryGetValue(cmd, out var command))
|
||||||
|
{
|
||||||
|
var context = new CommandContext(cmd, args.Length > 1 ? args[1] : null, command);
|
||||||
|
await _pipeline.ExecuteAsync(context);
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Warn("Неизвестная команда. Введите '/help'.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
namespace Govor.ConsoleClient.Services;
|
||||||
|
|
||||||
|
public class ConsoleLogger : ILogger
|
||||||
|
{
|
||||||
|
public void Log(string message)
|
||||||
|
{
|
||||||
|
Console.ResetColor();
|
||||||
|
Console.WriteLine(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Info(string message)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
|
Console.WriteLine($"[INFO] {message}");
|
||||||
|
Console.ResetColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Warn(string message)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
|
Console.WriteLine($"[WARN] {message}");
|
||||||
|
Console.ResetColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Error(string message)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Console.WriteLine($"[ERROR] {message}");
|
||||||
|
Console.ResetColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Title(string message)
|
||||||
|
{
|
||||||
|
var upper = message.ToUpper();
|
||||||
|
var length = upper.Length + 6;
|
||||||
|
var border = new string('=', length);
|
||||||
|
var padded = $"= {upper} =";
|
||||||
|
|
||||||
|
Console.ForegroundColor = ConsoleColor.Cyan;
|
||||||
|
Console.WriteLine(border);
|
||||||
|
Console.WriteLine(padded);
|
||||||
|
Console.WriteLine(border);
|
||||||
|
Console.ResetColor();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Govor.ConsoleClient.Services;
|
||||||
|
|
||||||
|
public interface ILogger
|
||||||
|
{
|
||||||
|
void Log(string message);
|
||||||
|
void Info(string message);
|
||||||
|
void Warn(string message);
|
||||||
|
void Error(string message);
|
||||||
|
void Title(string title);
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
using Govor.ConsoleClient.Commands;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Services;
|
||||||
|
|
||||||
|
public class InputPipeline
|
||||||
|
{
|
||||||
|
private readonly CommandDispatcher _dispatcher;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
private IInteractiveCommand? _activeCommand;
|
||||||
|
|
||||||
|
public InputPipeline(CommandDispatcher dispatcher, ILogger logger)
|
||||||
|
{
|
||||||
|
_dispatcher = dispatcher;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ProcessInputAsync(string input)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(input)) return;
|
||||||
|
|
||||||
|
if (input.StartsWith("/"))
|
||||||
|
{
|
||||||
|
_activeCommand = null; // Сброс активной команды
|
||||||
|
|
||||||
|
var commandInput = input[1..];
|
||||||
|
var result = await _dispatcher.DispatchAsync(commandInput);
|
||||||
|
|
||||||
|
// Если команда поддерживает интерактивность, сохраняем как активную
|
||||||
|
if (result is IInteractiveCommand interactiveCommand && !interactiveCommand.IsCompleted)
|
||||||
|
{
|
||||||
|
_activeCommand = interactiveCommand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_activeCommand != null)
|
||||||
|
{
|
||||||
|
await _activeCommand.HandleInputAsync(input);
|
||||||
|
|
||||||
|
if (_activeCommand.IsCompleted)
|
||||||
|
_activeCommand = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Info($"[Ввод пользователя]: {input}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
namespace Govor.ConsoleClient.Services.Middleware;
|
||||||
|
|
||||||
|
public class ExceptionHandlingMiddleware : ICommandMiddleware
|
||||||
|
{
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
public ExceptionHandlingMiddleware(ILogger logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task InvokeAsync(CommandContext context, Func<Task> next)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await next();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Error($"Произошла ошибка при выполнении команды '{context.Route}': {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Govor.ConsoleClient.Services.Middleware;
|
||||||
|
|
||||||
|
public interface ICommandMiddleware
|
||||||
|
{
|
||||||
|
Task InvokeAsync(CommandContext context, Func<Task> next);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using Govor.ConsoleClient.Services.Middleware;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Services;
|
||||||
|
|
||||||
|
public delegate Task CommandMiddleware(CommandContext context, Func<Task> next);
|
||||||
|
|
||||||
|
public class MiddlewarePipeline
|
||||||
|
{
|
||||||
|
private readonly IList<ICommandMiddleware> _middlewares;
|
||||||
|
|
||||||
|
public MiddlewarePipeline(IEnumerable<ICommandMiddleware> middlewares)
|
||||||
|
{
|
||||||
|
_middlewares = middlewares.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task ExecuteAsync(CommandContext context)
|
||||||
|
{
|
||||||
|
return InvokeNext(0, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task InvokeNext(int index, CommandContext context)
|
||||||
|
{
|
||||||
|
if (index < _middlewares.Count)
|
||||||
|
{
|
||||||
|
return _middlewares[index].InvokeAsync(context, () => InvokeNext(index + 1, context));
|
||||||
|
}
|
||||||
|
return context.Command.ExecuteAsync(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Govor.Core", "Govor.Core\Go
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Govor.Data", "Govor.Data\Govor.Data.csproj", "{E4EDB179-7EB5-468D-9C1F-0CBE2E5E459E}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Govor.Data", "Govor.Data\Govor.Data.csproj", "{E4EDB179-7EB5-468D-9C1F-0CBE2E5E459E}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Govor.Console", "Govor.Console\Govor.Console.csproj", "{F4535DC3-BDFB-4EB2-B259-F92B6BBB535B}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Govor.ConsoleClient", "Govor.ConsoleClient\Govor.ConsoleClient.csproj", "{F4535DC3-BDFB-4EB2-B259-F92B6BBB535B}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{4ED5259A-6FB4-4D89-8E6B-4778DC68F7D4}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{4ED5259A-6FB4-4D89-8E6B-4778DC68F7D4}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|||||||
Reference in New Issue
Block a user