mirror of
https://github.com/Govor-team/Govor.git
synced 2026-07-21 11:44:56 +00:00
I refactored Govor.Console to use the command pattern. Here's what I did:
- I implemented a command-based architecture for Govor.Console. - Each of your actions (e.g., login, send friend request, list friends) is now encapsulated in its own command class inheriting from BaseCommand. - I integrated friend-related functionalities (search, list, send/accept/reject request, block/unblock) using a mix of SignalR Hub and REST API calls. - I included admin functionalities for managing friendships (list all, list user's, remove). - I added a /help (-h) command to display available commands and their usage. - I refactored Program.cs to handle command parsing and execution. - I updated FriendsClient.cs, removing methods now handled directly by commands via SignalR. - I added SignalR event handlers for real-time notifications (friend requests, accepts, etc.).
This commit is contained in:
@@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands
|
||||||
|
{
|
||||||
|
public class AcceptFriendRequestCommand : BaseCommand
|
||||||
|
{
|
||||||
|
public override async Task ExecuteAsync(string? argument)
|
||||||
|
{
|
||||||
|
if (!EnsureLoggedIn() || !EnsureHubConnection()) return;
|
||||||
|
|
||||||
|
Guid friendshipId;
|
||||||
|
if (string.IsNullOrWhiteSpace(argument) || !Guid.TryParse(argument, out friendshipId))
|
||||||
|
{
|
||||||
|
Console.Write("Введите ID заявки, которую хотите принять: ");
|
||||||
|
var input = Console.ReadLine();
|
||||||
|
if (string.IsNullOrWhiteSpace(input) || !Guid.TryParse(input, out friendshipId))
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Ошибка] Неверный или пустой ID заявки.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// API uses Hub for this: AcceptFriendRequest(Guid friendshipId)
|
||||||
|
await HubConnection.InvokeAsync("AcceptFriendRequest", friendshipId);
|
||||||
|
Console.WriteLine("Заявка в друзья принята.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Ошибка принятия заявки] {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetHelp()
|
||||||
|
{
|
||||||
|
return "/accept [ID_заявки] - Принять входящую заявку в друзья. Если ID не указан, запросит ввод.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Govor.Contracts.DTOs; // Required for FriendshipDto
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands
|
||||||
|
{
|
||||||
|
public class AdminListAllFriendshipsCommand : BaseCommand
|
||||||
|
{
|
||||||
|
public override async Task ExecuteAsync(string? argument)
|
||||||
|
{
|
||||||
|
if (!EnsureLoggedIn()) return;
|
||||||
|
// Consider adding an admin role check here if possible,
|
||||||
|
// though the API itself is protected by [Authorize(Roles = "Admin")]
|
||||||
|
|
||||||
|
Console.WriteLine("Получение всех дружеских связей (только для администраторов)...");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await HttpClientService.GetAsync("api/admin/Friendships");
|
||||||
|
if (response.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Ошибка] Доступ запрещен. Эта команда только для администраторов.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var friendships = await response.Content.ReadFromJsonAsync<List<FriendshipDto>>();
|
||||||
|
|
||||||
|
if (friendships != null && friendships.Any())
|
||||||
|
{
|
||||||
|
Console.WriteLine("Все дружеские связи в системе:");
|
||||||
|
foreach (var f in friendships)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"- ID: {f.Id}, Пользователь1: {f.RequesterId}, Пользователь2: {f.AddresseeId}, Статус: {f.Status}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("Дружеские связи не найдены в системе.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (HttpRequestException httpEx) when (httpEx.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Ошибка] Доступ запрещен. Эта команда только для администраторов.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Ошибка] {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetHelp()
|
||||||
|
{
|
||||||
|
return "/adminlistallfs - (Админ) Показать все дружеские связи в системе.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Govor.Contracts.DTOs; // Required for FriendshipDto
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands
|
||||||
|
{
|
||||||
|
public class AdminListUserFriendshipsCommand : BaseCommand
|
||||||
|
{
|
||||||
|
public override async Task ExecuteAsync(string? argument)
|
||||||
|
{
|
||||||
|
if (!EnsureLoggedIn()) return;
|
||||||
|
|
||||||
|
Guid userId;
|
||||||
|
if (string.IsNullOrWhiteSpace(argument) || !Guid.TryParse(argument, out userId))
|
||||||
|
{
|
||||||
|
Console.Write("Введите ID пользователя для просмотра его связей: ");
|
||||||
|
var input = Console.ReadLine();
|
||||||
|
if (string.IsNullOrWhiteSpace(input) || !Guid.TryParse(input, out userId))
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Ошибка] Неверный или пустой ID пользователя.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"Получение всех связей для пользователя {userId} (только для администраторов)...");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await HttpClientService.GetAsync($"api/admin/Friendships/{userId}");
|
||||||
|
if (response.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Ошибка] Доступ запрещен. Эта команда только для администраторов.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var friendships = await response.Content.ReadFromJsonAsync<List<FriendshipDto>>();
|
||||||
|
|
||||||
|
if (friendships != null && friendships.Any())
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Дружеские связи для пользователя {userId}:");
|
||||||
|
foreach (var f in friendships)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"- ID: {f.Id}, Пользователь1: {f.RequesterId}, Пользователь2: {f.AddresseeId}, Статус: {f.Status}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Дружеские связи для пользователя {userId} не найдены.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (HttpRequestException httpEx) when (httpEx.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Ошибка] Доступ запрещен. Эта команда только для администраторов.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Ошибка] {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetHelp()
|
||||||
|
{
|
||||||
|
return "/adminlistuserfs [ID_пользователя] - (Админ) Показать все дружеские связи для указанного пользователя. Если ID не указан, запросит ввод.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands
|
||||||
|
{
|
||||||
|
public class AdminRemoveFriendshipCommand : BaseCommand
|
||||||
|
{
|
||||||
|
public override async Task ExecuteAsync(string? argument)
|
||||||
|
{
|
||||||
|
if (!EnsureLoggedIn()) return;
|
||||||
|
|
||||||
|
Guid friendshipId;
|
||||||
|
if (string.IsNullOrWhiteSpace(argument) || !Guid.TryParse(argument, out friendshipId))
|
||||||
|
{
|
||||||
|
Console.Write("Введите ID дружеской связи для удаления: ");
|
||||||
|
var input = Console.ReadLine();
|
||||||
|
if (string.IsNullOrWhiteSpace(input) || !Guid.TryParse(input, out friendshipId))
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Ошибка] Неверный или пустой ID связи.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"Удаление дружеской связи {friendshipId} (только для администраторов)...");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// The API endpoint is: [HttpPost] public async Task<IActionResult> RemoveFriendship(Guid Id)
|
||||||
|
// It expects the Id in the query string, like: api/admin/Friendships?Id=GUID
|
||||||
|
// Or it might be a POST with x-www-form-urlencoded data or JSON body, need to check API implementation.
|
||||||
|
// Based on `[HttpPost] public async Task<IActionResult> RemoveFriendship(Guid Id)`, it's likely a query parameter or form data.
|
||||||
|
// Let's assume query parameter for now as it's simpler for HttpPost.
|
||||||
|
|
||||||
|
var response = await HttpClientService.PostAsync($"api/admin/Friendships?Id={friendshipId}", null);
|
||||||
|
|
||||||
|
if (response.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Ошибка] Доступ запрещен. Эта команда только для администраторов.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
Console.WriteLine($"Дружеская связь {friendshipId} успешно удалена.");
|
||||||
|
}
|
||||||
|
catch (HttpRequestException httpEx) when (httpEx.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Ошибка] Доступ запрещен. Эта команда только для администраторов.");
|
||||||
|
}
|
||||||
|
catch (HttpRequestException httpEx) when (httpEx.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Ошибка] Дружеская связь с ID {friendshipId} не найдена.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Ошибка] {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetHelp()
|
||||||
|
{
|
||||||
|
return "/adminremovefs [ID_связи] - (Админ) Удалить дружескую связь по ее ID. Если ID не указан, запросит ввод.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands
|
||||||
|
{
|
||||||
|
public abstract class BaseCommand : ICommand
|
||||||
|
{
|
||||||
|
protected static FriendsClient? FriendsClient { get; private set; }
|
||||||
|
protected static HttpClientService HttpClientService { get; private set; }
|
||||||
|
protected static Func<string?> GetAuthToken { get; private set; }
|
||||||
|
protected static Action<string> SetAuthToken { get; private set; }
|
||||||
|
protected static Func<Task> InitializeHubConnectionAsync { get; private set; }
|
||||||
|
protected static Microsoft.AspNetCore.SignalR.Client.HubConnection? HubConnection => _hubConnection?.Invoke();
|
||||||
|
private static Func<Microsoft.AspNetCore.SignalR.Client.HubConnection?> _hubConnection;
|
||||||
|
|
||||||
|
|
||||||
|
public static void InitializeServices(
|
||||||
|
FriendsClient? friendsClient,
|
||||||
|
HttpClientService httpClientService,
|
||||||
|
Func<string?> getAuthToken,
|
||||||
|
Action<string> setAuthToken,
|
||||||
|
Func<Task> initializeHubConnectionAsync,
|
||||||
|
Func<Microsoft.AspNetCore.SignalR.Client.HubConnection?> hubConnection)
|
||||||
|
{
|
||||||
|
FriendsClient = friendsClient;
|
||||||
|
HttpClientService = httpClientService;
|
||||||
|
GetAuthToken = getAuthToken;
|
||||||
|
SetAuthToken = setAuthToken;
|
||||||
|
InitializeHubConnectionAsync = initializeHubConnectionAsync;
|
||||||
|
_hubConnection = hubConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Task ExecuteAsync(string? argument);
|
||||||
|
public abstract string GetHelp();
|
||||||
|
|
||||||
|
protected boolEnsureLoggedIn()
|
||||||
|
{
|
||||||
|
if (GetAuthToken() == null)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("[Ошибка] Сначала войдите в систему. Используйте /login или /reg.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (FriendsClient == null && !(this is LoginCommand || this is RegisterCommand)) // FriendsClient might not be needed for auth commands
|
||||||
|
{
|
||||||
|
// Attempt to re-initialize FriendsClient if token exists but client is null
|
||||||
|
// This can happen if the app was closed and token was persisted, but client was not re-instantiated.
|
||||||
|
// However, the current setup in Program.cs initializes FriendsClient after login/reg.
|
||||||
|
// This check is more of a safeguard.
|
||||||
|
System.Console.WriteLine("[Ошибка] Клиент для работы с друзьями не инициализирован. Попробуйте войти снова.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolEnsureHubConnection()
|
||||||
|
{
|
||||||
|
if (HubConnection == null || HubConnection.State != Microsoft.AspNetCore.SignalR.Client.HubConnectionState.Connected)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("[Ошибка] SignalR соединение не установлено. Попробуйте войти снова или проверьте соединение.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands
|
||||||
|
{
|
||||||
|
public class BlockUserCommand : BaseCommand
|
||||||
|
{
|
||||||
|
public override async Task ExecuteAsync(string? argument)
|
||||||
|
{
|
||||||
|
if (!EnsureLoggedIn() || !EnsureHubConnection()) return;
|
||||||
|
|
||||||
|
Guid targetUserId;
|
||||||
|
if (string.IsNullOrWhiteSpace(argument) || !Guid.TryParse(argument, out targetUserId))
|
||||||
|
{
|
||||||
|
Console.Write("Введите ID пользователя, которого хотите заблокировать: ");
|
||||||
|
var input = Console.ReadLine();
|
||||||
|
if (string.IsNullOrWhiteSpace(input) || !Guid.TryParse(input, out targetUserId))
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Ошибка] Неверный или пустой ID пользователя.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// API uses Hub for this: BlockUser(Guid targetUserId)
|
||||||
|
// Located in Govor.API/Hubs/FriendsHub.cs
|
||||||
|
await HubConnection.InvokeAsync("BlockUser", targetUserId);
|
||||||
|
Console.WriteLine($"Пользователь {targetUserId} заблокирован.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Ошибка блокировки пользователя] {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetHelp()
|
||||||
|
{
|
||||||
|
return "/block [ID_пользователя] - Заблокировать пользователя. Если ID не указан, запросит ввод.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands
|
||||||
|
{
|
||||||
|
public class HelpCommand : BaseCommand
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, ICommand> _availableCommands;
|
||||||
|
|
||||||
|
// The HelpCommand needs access to the list of all commands to display their help messages.
|
||||||
|
// This will be injected from Program.cs where the commands are registered.
|
||||||
|
public HelpCommand(Dictionary<string, ICommand> availableCommands)
|
||||||
|
{
|
||||||
|
_availableCommands = availableCommands;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task ExecuteAsync(string? argument)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Доступные команды:");
|
||||||
|
if (!string.IsNullOrWhiteSpace(argument))
|
||||||
|
{
|
||||||
|
string commandKey = argument.StartsWith("/") ? argument : "/" + argument;
|
||||||
|
if (_availableCommands.TryGetValue(commandKey.ToLower(), out var specificCommand))
|
||||||
|
{
|
||||||
|
Console.WriteLine(specificCommand.GetHelp());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Команда '{argument}' не найдена. Введите /help для списка всех команд.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var commandEntry in _availableCommands.OrderBy(c => c.Key))
|
||||||
|
{
|
||||||
|
Console.WriteLine(commandEntry.Value.GetHelp());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetHelp()
|
||||||
|
{
|
||||||
|
return "/help [команда] - Показать список всех команд или помощь по конкретной команде.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Govor.ConsoleClient.Commands
|
||||||
|
{
|
||||||
|
public interface ICommand
|
||||||
|
{
|
||||||
|
Task ExecuteAsync(string? argument);
|
||||||
|
string GetHelp();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands
|
||||||
|
{
|
||||||
|
public class ListFriendsCommand : BaseCommand
|
||||||
|
{
|
||||||
|
public override async Task ExecuteAsync(string? argument)
|
||||||
|
{
|
||||||
|
if (!EnsureLoggedIn()) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var friends = await FriendsClient.GetFriendsAsync();
|
||||||
|
if (friends.Any())
|
||||||
|
{
|
||||||
|
Console.WriteLine("Ваши друзья:");
|
||||||
|
foreach (var f in friends)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"- {f.Username} | был онлайн: {f.WasOnline} [{f.Id}]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("У вас пока нет друзей.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Ошибка] {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetHelp()
|
||||||
|
{
|
||||||
|
return "/friends - Показать список ваших друзей.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands
|
||||||
|
{
|
||||||
|
public class ListIncomingRequestsCommand : BaseCommand
|
||||||
|
{
|
||||||
|
public override async Task ExecuteAsync(string? argument)
|
||||||
|
{
|
||||||
|
if (!EnsureLoggedIn()) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// This still uses REST client as per existing FriendsClient
|
||||||
|
var requests = await FriendsClient.GetIncomingRequestsAsync();
|
||||||
|
if (requests.Any())
|
||||||
|
{
|
||||||
|
Console.WriteLine("Входящие заявки в друзья:");
|
||||||
|
foreach (var r in requests)
|
||||||
|
{
|
||||||
|
// Assuming you want to show who sent the request.
|
||||||
|
// The FriendshipDto contains RequesterId and AddresseeId.
|
||||||
|
// If current user is AddresseeId, then RequesterId is the one who sent it.
|
||||||
|
Console.WriteLine($"- Запрос ID: {r.Id}. От пользователя ID: {r.RequesterId}. Статус: {r.Status}. (принять через /accept {r.Id})");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("У вас нет входящих заявок в друзья.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Ошибка] {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetHelp()
|
||||||
|
{
|
||||||
|
return "/incoming - Показать список входящих заявок в друзья.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Govor.Contracts.DTOs; // Required for FriendshipDto
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands
|
||||||
|
{
|
||||||
|
public class ListOutgoingRequestsCommand : BaseCommand
|
||||||
|
{
|
||||||
|
public override async Task ExecuteAsync(string? argument)
|
||||||
|
{
|
||||||
|
if (!EnsureLoggedIn()) return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// This functionality maps to GET api/friends/responses in FriendsRequestQueryController
|
||||||
|
// FriendsClient doesn't have a dedicated method, so we use HttpClientService or direct HttpClient
|
||||||
|
var response = await HttpClientService.GetAsync("api/friends/responses");
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
var requests = await response.Content.ReadFromJsonAsync<System.Collections.Generic.List<FriendshipDto>>();
|
||||||
|
|
||||||
|
if (requests != null && requests.Any())
|
||||||
|
{
|
||||||
|
Console.WriteLine("Отправленные вами заявки в друзья (ожидают ответа):");
|
||||||
|
foreach (var r in requests)
|
||||||
|
{
|
||||||
|
// If current user is RequesterId, then AddresseeId is the one they sent to.
|
||||||
|
Console.WriteLine($"- Запрос ID: {r.Id}. Пользователю ID: {r.AddresseeId}. Статус: {r.Status}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("У вас нет отправленных заявок, ожидающих ответа.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Ошибка] {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetHelp()
|
||||||
|
{
|
||||||
|
return "/outgoing - Показать список отправленных вами заявок в друзья, ожидающих ответа.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands
|
||||||
|
{
|
||||||
|
public class LoginCommand : BaseCommand
|
||||||
|
{
|
||||||
|
public override async Task ExecuteAsync(string? argument)
|
||||||
|
{
|
||||||
|
Console.Write("username: ");
|
||||||
|
var loginUsername = Console.ReadLine();
|
||||||
|
|
||||||
|
Console.Write("password: ");
|
||||||
|
var loginPassword = Console.ReadLine();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(loginUsername) || string.IsNullOrWhiteSpace(loginPassword))
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Ошибка] Имя пользователя и пароль не могут быть пустыми.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var authToken = await HttpClientService.LoginAsync(loginUsername, loginPassword);
|
||||||
|
SetAuthToken(authToken);
|
||||||
|
|
||||||
|
// Initialize FriendsClient after successful login
|
||||||
|
var sharedClient = new HttpClient { BaseAddress = new Uri(HttpClientService.GetBaseUrl()) };
|
||||||
|
sharedClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
|
||||||
|
var friendsClient = new FriendsClient(sharedClient);
|
||||||
|
|
||||||
|
// Re-initialize services in BaseCommand with the new FriendsClient
|
||||||
|
InitializeServices(friendsClient, HttpClientService, GetAuthToken, SetAuthToken, InitializeHubConnectionAsync, HubConnection);
|
||||||
|
|
||||||
|
await InitializeHubConnectionAsync();
|
||||||
|
Console.WriteLine("[Успех] Вход выполнен. Токен сохранен.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Ошибка] {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetHelp()
|
||||||
|
{
|
||||||
|
return "/login - Войти в существующий аккаунт.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands
|
||||||
|
{
|
||||||
|
public class RegisterCommand : BaseCommand
|
||||||
|
{
|
||||||
|
public override async Task ExecuteAsync(string? argument)
|
||||||
|
{
|
||||||
|
Console.Write("username: ");
|
||||||
|
var regUsername = Console.ReadLine();
|
||||||
|
|
||||||
|
Console.Write("password: ");
|
||||||
|
var regPassword = Console.ReadLine();
|
||||||
|
|
||||||
|
Console.Write("invitation code: ");
|
||||||
|
var inviteCode = Console.ReadLine();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(regUsername) || string.IsNullOrWhiteSpace(regPassword) || string.IsNullOrWhiteSpace(inviteCode))
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Ошибка] Имя пользователя, пароль и код приглашения не могут быть пустыми.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var authToken = await HttpClientService.RegisterAsync(regUsername, regPassword, inviteCode);
|
||||||
|
SetAuthToken(authToken);
|
||||||
|
|
||||||
|
// Initialize FriendsClient after successful registration
|
||||||
|
var sharedClient = new HttpClient { BaseAddress = new Uri(HttpClientService.GetBaseUrl()) };
|
||||||
|
sharedClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
|
||||||
|
var friendsClient = new FriendsClient(sharedClient);
|
||||||
|
|
||||||
|
// Re-initialize services in BaseCommand with the new FriendsClient
|
||||||
|
InitializeServices(friendsClient, HttpClientService, GetAuthToken, SetAuthToken, InitializeHubConnectionAsync, HubConnection);
|
||||||
|
|
||||||
|
await InitializeHubConnectionAsync();
|
||||||
|
Console.WriteLine("[Успех] Регистрация завершена. Токен сохранен.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Ошибка] {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetHelp()
|
||||||
|
{
|
||||||
|
return "/reg - Зарегистрировать новый аккаунт с помощью кода приглашения.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands
|
||||||
|
{
|
||||||
|
public class RejectFriendRequestCommand : BaseCommand
|
||||||
|
{
|
||||||
|
public override async Task ExecuteAsync(string? argument)
|
||||||
|
{
|
||||||
|
if (!EnsureLoggedIn() || !EnsureHubConnection()) return;
|
||||||
|
|
||||||
|
Guid friendshipId;
|
||||||
|
if (string.IsNullOrWhiteSpace(argument) || !Guid.TryParse(argument, out friendshipId))
|
||||||
|
{
|
||||||
|
Console.Write("Введите ID заявки, которую хотите отклонить: ");
|
||||||
|
var input = Console.ReadLine();
|
||||||
|
if (string.IsNullOrWhiteSpace(input) || !Guid.TryParse(input, out friendshipId))
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Ошибка] Неверный или пустой ID заявки.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// API uses Hub for this: RejectFriendRequest(Guid friendshipId)
|
||||||
|
// Located in Govor.API/Hubs/FriendsHub.cs
|
||||||
|
await HubConnection.InvokeAsync("RejectFriendRequest", friendshipId);
|
||||||
|
Console.WriteLine("Заявка в друзья отклонена.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Ошибка отклонения заявки] {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetHelp()
|
||||||
|
{
|
||||||
|
return "/reject [ID_заявки] - Отклонить входящую заявку в друзья. Если ID не указан, запросит ввод.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands
|
||||||
|
{
|
||||||
|
public class SearchUserCommand : BaseCommand
|
||||||
|
{
|
||||||
|
public override async Task ExecuteAsync(string? argument)
|
||||||
|
{
|
||||||
|
if (!EnsureLoggedIn()) return;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(argument))
|
||||||
|
{
|
||||||
|
Console.Write("Введите имя пользователя для поиска: ");
|
||||||
|
argument = Console.ReadLine();
|
||||||
|
if (string.IsNullOrWhiteSpace(argument))
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Ошибка] Поисковый запрос не может быть пустым.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var foundUsers = await FriendsClient.SearchAsync(argument);
|
||||||
|
if (foundUsers.Any())
|
||||||
|
{
|
||||||
|
Console.WriteLine("Найденные пользователи:");
|
||||||
|
foreach (var user in foundUsers)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"- {user.Username} [{user.Id}]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("Пользователи не найдены.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Ошибка] {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetHelp()
|
||||||
|
{
|
||||||
|
return "/search [имя_пользователя] - Найти пользователей по имени. Если имя не указано, запросит ввод.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands
|
||||||
|
{
|
||||||
|
public class SendFriendRequestCommand : BaseCommand
|
||||||
|
{
|
||||||
|
public override async Task ExecuteAsync(string? argument)
|
||||||
|
{
|
||||||
|
if (!EnsureLoggedIn() || !EnsureHubConnection()) return;
|
||||||
|
|
||||||
|
Guid targetUserId;
|
||||||
|
if (string.IsNullOrWhiteSpace(argument) || !Guid.TryParse(argument, out targetUserId))
|
||||||
|
{
|
||||||
|
Console.Write("Введите ID пользователя, которому хотите отправить запрос: ");
|
||||||
|
var input = Console.ReadLine();
|
||||||
|
if (string.IsNullOrWhiteSpace(input) || !Guid.TryParse(input, out targetUserId))
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Ошибка] Неверный или пустой ID пользователя.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// API uses Hub for this: SendFriendRequest(Guid targetUserId)
|
||||||
|
await HubConnection.InvokeAsync("SendFriendRequest", targetUserId);
|
||||||
|
Console.WriteLine("Запрос в друзья отправлен.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Ошибка отправки запроса] {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetHelp()
|
||||||
|
{
|
||||||
|
return "/friend [ID_пользователя] - Отправить запрос в друзья пользователю с указанным ID. Если ID не указан, запросит ввод.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Govor.ConsoleClient.Commands
|
||||||
|
{
|
||||||
|
public class UnblockUserCommand : BaseCommand
|
||||||
|
{
|
||||||
|
public override async Task ExecuteAsync(string? argument)
|
||||||
|
{
|
||||||
|
if (!EnsureLoggedIn() || !EnsureHubConnection()) return;
|
||||||
|
|
||||||
|
Guid targetUserId;
|
||||||
|
if (string.IsNullOrWhiteSpace(argument) || !Guid.TryParse(argument, out targetUserId))
|
||||||
|
{
|
||||||
|
Console.Write("Введите ID пользователя, которого хотите разблокировать: ");
|
||||||
|
var input = Console.ReadLine();
|
||||||
|
if (string.IsNullOrWhiteSpace(input) || !Guid.TryParse(input, out targetUserId))
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Ошибка] Неверный или пустой ID пользователя.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// API uses Hub for this: UnblockUser(Guid targetUserId)
|
||||||
|
// Located in Govor.API/Hubs/FriendsHub.cs
|
||||||
|
await HubConnection.InvokeAsync("UnblockUser", targetUserId);
|
||||||
|
Console.WriteLine($"Пользователь {targetUserId} разблокирован.");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Ошибка разблокировки пользователя] {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string GetHelp()
|
||||||
|
{
|
||||||
|
return "/unblock [ID_пользователя] - Разблокировать пользователя. Если ID не указан, запросит ввод.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using Govor.Contracts.DTOs;
|
using Govor.Contracts.DTOs;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks; // Added for Task
|
||||||
|
|
||||||
namespace Govor.ConsoleClient
|
namespace Govor.ConsoleClient
|
||||||
{
|
{
|
||||||
@@ -20,11 +23,12 @@ namespace Govor.ConsoleClient
|
|||||||
return await response.Content.ReadFromJsonAsync<List<UserDto>>() ?? new List<UserDto>();
|
return await response.Content.ReadFromJsonAsync<List<UserDto>>() ?? new List<UserDto>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SendFriendRequestAsync(Guid targetUserId)
|
// 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();
|
// var response = await _client.PostAsync($"api/friends/request?targetUserId={targetUserId}", null);
|
||||||
}
|
// response.EnsureSuccessStatusCode();
|
||||||
|
// }
|
||||||
|
|
||||||
public async Task<List<FriendshipDto>> GetIncomingRequestsAsync()
|
public async Task<List<FriendshipDto>> GetIncomingRequestsAsync()
|
||||||
{
|
{
|
||||||
@@ -34,11 +38,12 @@ namespace Govor.ConsoleClient
|
|||||||
return await response.Content.ReadFromJsonAsync<List<FriendshipDto>>() ?? new List<FriendshipDto>();
|
return await response.Content.ReadFromJsonAsync<List<FriendshipDto>>() ?? new List<FriendshipDto>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AcceptFriendRequestAsync(Guid requesterId)
|
// 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={requesterId}", null);
|
// {
|
||||||
response.EnsureSuccessStatusCode();
|
// var response = await _client.PostAsync($"/api/friends/accept?friendshipId={friendshipId}", null);
|
||||||
}
|
// response.EnsureSuccessStatusCode();
|
||||||
|
// }
|
||||||
|
|
||||||
public async Task<List<UserDto>> GetFriendsAsync()
|
public async Task<List<UserDto>> GetFriendsAsync()
|
||||||
{
|
{
|
||||||
@@ -49,4 +54,4 @@ namespace Govor.ConsoleClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+202
-191
@@ -1,13 +1,14 @@
|
|||||||
using Microsoft.AspNetCore.SignalR.Client;
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Net.Http.Json;
|
using System.Threading.Tasks;
|
||||||
using System.Text.Json;
|
using Govor.ConsoleClient.Commands;
|
||||||
using Govor.Contracts.Requests;
|
|
||||||
using Govor.Contracts.Requests.SignalR;
|
using Govor.Contracts.Requests.SignalR;
|
||||||
using Govor.Contracts.Responses.SignalR;
|
using Govor.Contracts.Responses.SignalR;
|
||||||
using Govor.Core.Models;
|
|
||||||
|
|
||||||
|
|
||||||
/*====================================
|
/*====================================
|
||||||
*Личные сообщения| Егор
|
*Личные сообщения| Егор
|
||||||
@@ -29,14 +30,26 @@ namespace Govor.ConsoleClient
|
|||||||
static string baseUrl = "https://localhost:7155";
|
static string baseUrl = "https://localhost:7155";
|
||||||
static string? AuthToken = null;
|
static string? AuthToken = null;
|
||||||
static HttpClientService HttpService = new(baseUrl);
|
static HttpClientService HttpService = new(baseUrl);
|
||||||
private static FriendsClient? friendsClient;
|
private static FriendsClient? _friendsClient; // Renamed to avoid conflict with BaseCommand
|
||||||
static HubConnection? _hubConnection;
|
static HubConnection? _hubConnection;
|
||||||
static Dictionary<string, List<string>> ChatHistory = new();
|
static Dictionary<string, List<string>> ChatHistory = new();
|
||||||
static string? CurrentChatUser = null;
|
static string? CurrentChatUser = null;
|
||||||
static Guid CurrentChatUserId = Guid.Empty;
|
static Guid CurrentChatUserId = Guid.Empty;
|
||||||
|
|
||||||
|
private static Dictionary<string, ICommand> _commands = new();
|
||||||
|
|
||||||
static async Task Main()
|
static async Task Main()
|
||||||
{
|
{
|
||||||
|
InitializeCommands();
|
||||||
|
BaseCommand.InitializeServices(
|
||||||
|
_friendsClient, // Initially null, will be set by Login/Register commands
|
||||||
|
HttpService,
|
||||||
|
() => AuthToken,
|
||||||
|
(token) => AuthToken = token,
|
||||||
|
InitializeHubConnection,
|
||||||
|
() => _hubConnection
|
||||||
|
);
|
||||||
|
|
||||||
LoginWindow();
|
LoginWindow();
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
@@ -47,170 +60,121 @@ namespace Govor.ConsoleClient
|
|||||||
if (string.IsNullOrWhiteSpace(input)) continue;
|
if (string.IsNullOrWhiteSpace(input)) continue;
|
||||||
|
|
||||||
if (input.StartsWith("/"))
|
if (input.StartsWith("/"))
|
||||||
HandleCommand(input);
|
await HandleCommandAsync(input);
|
||||||
else if (CurrentChatUser != null)
|
else if (CurrentChatUser != null)
|
||||||
SendMessage(input);
|
await SendMessageAsync(input);
|
||||||
else
|
else
|
||||||
Console.WriteLine("[Система] Введите команду, например /friends");
|
Console.WriteLine("[Система] Введите команду, например /help или /friends");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async void HandleCommand(string input)
|
static void InitializeCommands()
|
||||||
{
|
{
|
||||||
var args = input.Split(' ', 2);
|
_commands = new Dictionary<string, ICommand>
|
||||||
var command = args[0].ToLower();
|
|
||||||
var argument = args.Length > 1 ? args[1] : null;
|
|
||||||
|
|
||||||
switch (command)
|
|
||||||
{
|
{
|
||||||
case "/login":
|
{ "/login", new LoginCommand() },
|
||||||
Console.Write("username: ");
|
{ "/reg", new RegisterCommand() },
|
||||||
var loginUsername = Console.ReadLine();
|
{ "/search", new SearchUserCommand() },
|
||||||
|
{ "/friends", new ListFriendsCommand() },
|
||||||
Console.Write("password: ");
|
{ "/friend", new SendFriendRequestCommand() }, // Alias for SendFriendRequest
|
||||||
var loginPassword = Console.ReadLine();
|
{ "/sendrequest", new SendFriendRequestCommand() },
|
||||||
|
{ "/accept", new AcceptFriendRequestCommand() },
|
||||||
try
|
{ "/reject", new RejectFriendRequestCommand() },
|
||||||
{
|
{ "/incoming", new ListIncomingRequestsCommand() },
|
||||||
AuthToken = await HttpService.LoginAsync(loginUsername, loginPassword);
|
{ "/outgoing", new ListOutgoingRequestsCommand() },
|
||||||
HttpClient sharedClient = new();
|
{ "/block", new BlockUserCommand() },
|
||||||
sharedClient.BaseAddress = new Uri(baseUrl);
|
{ "/unblock", new UnblockUserCommand() },
|
||||||
sharedClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AuthToken);
|
|
||||||
|
|
||||||
friendsClient = new FriendsClient(sharedClient);
|
|
||||||
await InitializeHubConnection();
|
|
||||||
Console.WriteLine("[Успех] Вход выполнен. Токен сохранен.");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"[Ошибка] {ex.Message}");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "/reg":
|
|
||||||
Console.Write("username: ");
|
|
||||||
var regUsername = Console.ReadLine();
|
|
||||||
|
|
||||||
Console.Write("password: ");
|
|
||||||
var regPassword = Console.ReadLine();
|
|
||||||
|
|
||||||
Console.Write("invitation: ");
|
|
||||||
var inviteCode = Console.ReadLine();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
AuthToken = await HttpService.RegisterAsync(regUsername, regPassword, inviteCode);
|
|
||||||
HttpClient sharedClient = new();
|
|
||||||
sharedClient.BaseAddress = new Uri(baseUrl);
|
|
||||||
sharedClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AuthToken);
|
|
||||||
|
|
||||||
friendsClient = new FriendsClient(sharedClient);
|
|
||||||
await InitializeHubConnection();
|
|
||||||
Console.WriteLine("[Успех] Регистрация завершена. Токен сохранен.");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"[Ошибка] {ex.Message}");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "/search":
|
|
||||||
if (friendsClient == null)
|
|
||||||
{
|
|
||||||
Console.WriteLine("[Ошибка] Сначала войдите в систему.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Console.Write("Введите имя друга: ");
|
|
||||||
var q = Console.ReadLine();
|
|
||||||
var foundUsers = await friendsClient.SearchAsync(q);
|
|
||||||
foreach (var user in foundUsers)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"{user.Username} [{user.Id}]");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "/exit":
|
{ "/adminlistallfs", new AdminListAllFriendshipsCommand() },
|
||||||
Console.WriteLine("[Система] Выход...");
|
{ "/adminlistuserfs", new AdminListUserFriendshipsCommand() },
|
||||||
if (_hubConnection != null)
|
{ "/adminremovefs", new AdminRemoveFriendshipCommand() },
|
||||||
{
|
// Help command is special as it needs the list of commands
|
||||||
await _hubConnection.StopAsync();
|
// It will be added after other commands are initialized
|
||||||
await _hubConnection.DisposeAsync();
|
};
|
||||||
}
|
_commands.Add("/help", new HelpCommand(_commands));
|
||||||
Environment.Exit(0);
|
_commands.Add("-h", new HelpCommand(_commands)); // Alias for help
|
||||||
break;
|
|
||||||
|
|
||||||
case "/friends":
|
// Add other general commands not refactored yet if any, or create classes for them
|
||||||
if (friendsClient == null)
|
// For example, /exit, /chat, /back will be handled separately for now or made into commands
|
||||||
{
|
}
|
||||||
Console.WriteLine("[Ошибка] Сначала войдите в систему.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
var friends = await friendsClient.GetFriendsAsync();
|
|
||||||
foreach (var f in friends)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"{f.Username} | был онлайн: {f.WasOnline} [{f.Id}]");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "/friend":
|
|
||||||
if (friendsClient == null)
|
|
||||||
{
|
|
||||||
Console.WriteLine("[Ошибка] Сначала войдите в систему.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Console.Write("Введите ID пользователя, которому хотите отправить запрос: ");
|
|
||||||
var targetId = Guid.Parse(Console.ReadLine());
|
|
||||||
await friendsClient.SendFriendRequestAsync(targetId);
|
|
||||||
Console.WriteLine("Запрос отправлен");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "/accept":
|
// Public static method to allow commands (like Login/Register) to update the FriendsClient
|
||||||
if (friendsClient == null)
|
public static void UpdateFriendsClient(FriendsClient newFriendsClient)
|
||||||
{
|
{
|
||||||
Console.WriteLine("[Ошибка] Сначала войдите в систему.");
|
_friendsClient = newFriendsClient;
|
||||||
break;
|
// Re-initialize services in BaseCommand with the new FriendsClient
|
||||||
}
|
BaseCommand.InitializeServices(
|
||||||
Console.Write("Введите ID заявки, которую хотите принять принимаете: ");
|
_friendsClient,
|
||||||
var acceptId = Guid.Parse(Console.ReadLine());
|
HttpService,
|
||||||
await friendsClient.AcceptFriendRequestAsync(acceptId);
|
() => AuthToken,
|
||||||
Console.WriteLine("Принято");
|
(token) => AuthToken = token,
|
||||||
break;
|
InitializeHubConnection,
|
||||||
case "/incoming":
|
() => _hubConnection
|
||||||
if (friendsClient == null)
|
);
|
||||||
{
|
}
|
||||||
Console.WriteLine("[Ошибка] Сначала войдите в систему.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
var requests = await friendsClient.GetIncomingRequestsAsync();
|
|
||||||
foreach (var r in requests)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Запрос от: {r.RequesterId} (добавьте через /accept {r.Id})");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "/chat":
|
|
||||||
if (string.IsNullOrEmpty(argument))
|
|
||||||
{
|
|
||||||
Console.WriteLine("[Ошибка] Укажите имя друга и ID через пробел (например /chat Egor GUID)");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var chatArgs = argument.Split(' ', 2);
|
|
||||||
if (chatArgs.Length < 2 || !Guid.TryParse(chatArgs[1], out var chatUserId))
|
static async Task HandleCommandAsync(string input)
|
||||||
{
|
{
|
||||||
Console.WriteLine("[Ошибка] Неверный формат. Укажите имя друга и ID (например /chat Egor GUID)");
|
var parts = input.Split(new[] { ' ' }, 2, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
var commandKey = parts[0].ToLower();
|
||||||
|
var argument = parts.Length > 1 ? parts[1] : null;
|
||||||
|
|
||||||
|
if (_commands.TryGetValue(commandKey, out var commandInstance))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await commandInstance.ExecuteAsync(argument);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Критическая ошибка выполнения команды {commandKey}]: {ex.Message}");
|
||||||
|
// Log detailed exception: Console.WriteLine(ex.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Handle non-refactored commands for now
|
||||||
|
switch (commandKey)
|
||||||
|
{
|
||||||
|
case "/exit":
|
||||||
|
Console.WriteLine("[Система] Выход...");
|
||||||
|
if (_hubConnection != null)
|
||||||
|
{
|
||||||
|
await _hubConnection.StopAsync();
|
||||||
|
await _hubConnection.DisposeAsync();
|
||||||
|
}
|
||||||
|
Environment.Exit(0);
|
||||||
break;
|
break;
|
||||||
}
|
case "/chat":
|
||||||
|
if (string.IsNullOrEmpty(argument))
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Ошибка] Укажите имя друга и ID через пробел (например /chat Egor GUID)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
CurrentChatUser = chatArgs[0];
|
var chatArgs = argument.Split(' ', 2);
|
||||||
CurrentChatUserId = chatUserId;
|
if (chatArgs.Length < 2 || !Guid.TryParse(chatArgs[1], out var chatUserId))
|
||||||
ShowChat(CurrentChatUser);
|
{
|
||||||
break;
|
Console.WriteLine("[Ошибка] Неверный формат. Укажите имя друга и ID (например /chat Egor GUID)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case "/back":
|
CurrentChatUser = chatArgs[0];
|
||||||
CurrentChatUser = null;
|
CurrentChatUserId = chatUserId;
|
||||||
CurrentChatUserId = Guid.Empty;
|
ShowChat(CurrentChatUser);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
case "/back":
|
||||||
Console.WriteLine("[Ошибка] Неизвестная команда");
|
CurrentChatUser = null;
|
||||||
break;
|
CurrentChatUserId = Guid.Empty;
|
||||||
|
Console.Clear(); // Optionally clear console when going back
|
||||||
|
LoginWindow(); // Or some other general view
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine($"[Ошибка] Неизвестная команда: {commandKey}. Введите /help для списка команд.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,10 +182,17 @@ namespace Govor.ConsoleClient
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(AuthToken))
|
if (string.IsNullOrEmpty(AuthToken))
|
||||||
{
|
{
|
||||||
|
// This check might be redundant if commands calling this ensure login first
|
||||||
Console.WriteLine("[Ошибка] Токен аутентификации отсутствует. Пожалуйста, войдите в систему.");
|
Console.WriteLine("[Ошибка] Токен аутентификации отсутствует. Пожалуйста, войдите в систему.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_hubConnection != null && _hubConnection.State != HubConnectionState.Disconnected)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[SignalR] Соединение уже установлено или устанавливается.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_hubConnection = new HubConnectionBuilder()
|
_hubConnection = new HubConnectionBuilder()
|
||||||
.WithUrl($"{baseUrl}/api/chats", options =>
|
.WithUrl($"{baseUrl}/api/chats", options =>
|
||||||
{
|
{
|
||||||
@@ -231,40 +202,76 @@ namespace Govor.ConsoleClient
|
|||||||
|
|
||||||
_hubConnection.On<UserMessageResponse>("ReceiveMessage", (message) =>
|
_hubConnection.On<UserMessageResponse>("ReceiveMessage", (message) =>
|
||||||
{
|
{
|
||||||
var senderName = message.SenderId == GetMyUserId() ? "Ты" : CurrentChatUser ?? "Неизвестно"; // Simplified for now
|
var myId = GetMyUserId();
|
||||||
|
var senderName = message.SenderId == myId ? "Ты" : CurrentChatUser ?? message.SenderUsername ?? "Неизвестно";
|
||||||
var displayMessage = $"[{message.SentAt:HH:mm}] {senderName} >> {message.EncryptedContent}";
|
var displayMessage = $"[{message.SentAt:HH:mm}] {senderName} >> {message.EncryptedContent}";
|
||||||
|
|
||||||
string chatKey = message.SenderId == GetMyUserId() ? message.RecipientId.ToString() : message.SenderId.ToString();
|
// Determine chat key based on sender/recipient, ensuring consistency
|
||||||
|
string chatKey = message.SenderId == myId ? message.RecipientId.ToString() : message.SenderId.ToString();
|
||||||
|
string activeChatDisplayUser = CurrentChatUser; // User whose chat window is open
|
||||||
|
|
||||||
if (CurrentChatUser != null && (message.SenderId == CurrentChatUserId || message.RecipientId == CurrentChatUserId))
|
// If the message belongs to the currently active chat window
|
||||||
|
if (CurrentChatUser != null && (message.SenderId == CurrentChatUserId || (message.RecipientId == CurrentChatUserId && message.SenderId == myId)))
|
||||||
{
|
{
|
||||||
if (!ChatHistory.ContainsKey(CurrentChatUser))
|
if (!ChatHistory.ContainsKey(activeChatDisplayUser))
|
||||||
{
|
{
|
||||||
ChatHistory[CurrentChatUser] = new List<string>();
|
ChatHistory[activeChatDisplayUser] = new List<string>();
|
||||||
}
|
}
|
||||||
ChatHistory[CurrentChatUser].Add(displayMessage);
|
ChatHistory[activeChatDisplayUser].Add(displayMessage);
|
||||||
Console.SetCursorPosition(0, Console.CursorTop); // Move cursor to beginning of line
|
|
||||||
Console.Write(new string(' ', Console.WindowWidth -1)); // Clear current line
|
// Smartly update console without disrupting user input too much
|
||||||
Console.SetCursorPosition(0, Console.CursorTop);
|
int originalCursorTop = Console.CursorTop;
|
||||||
Console.WriteLine($" * {displayMessage}"); // Display new message
|
int originalCursorLeft = Console.CursorLeft;
|
||||||
Console.Write(">> "); // Re-display prompt
|
Console.MoveBufferArea(0, originalCursorTop, Console.BufferWidth, 1, 0, originalCursorTop +1); // scroll current line down
|
||||||
|
Console.SetCursorPosition(0, originalCursorTop);
|
||||||
|
Console.WriteLine($" * {displayMessage}");
|
||||||
|
Console.SetCursorPosition(originalCursorLeft, originalCursorTop +1); // +1 because writeline added a line
|
||||||
|
Console.Write(">> "); // Re-display prompt part
|
||||||
}
|
}
|
||||||
else
|
else // Notification for message not in the current chat
|
||||||
{
|
{
|
||||||
// Handle notification for messages not in the current chat - TBD
|
Console.WriteLine($"\n[Новое сообщение от {message.SenderUsername ?? message.SenderId.ToString()}]: {message.EncryptedContent}");
|
||||||
Console.WriteLine($"\n[Новое сообщение от {message.SenderId}]: {message.EncryptedContent}");
|
Console.Write(CurrentChatUser == null ? "/> " : ">> "); // Re-display prompt
|
||||||
Console.Write(CurrentChatUser == null ? "/> " : ">> ");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_hubConnection.On<UserMessageResponse>("MessageSent", (message) =>
|
_hubConnection.On<UserMessageResponse>("MessageSent", (message) =>
|
||||||
{
|
{
|
||||||
// Optional: Handle confirmation that message was sent successfully by the server
|
// Optional: Handle confirmation that message was sent successfully by the server
|
||||||
// This could be useful for updating UI to show message status (e.g., "sent", "delivered")
|
// For console, maybe a subtle notification or log if verbose mode is on.
|
||||||
// For console, just logging or ignoring might be fine.
|
// Example: Console.WriteLine($"[Система] Сообщение для {message.RecipientUsername} доставлено на сервер.");
|
||||||
// Console.WriteLine($"[Система] Сообщение {message.MessageId} доставлено на сервер.");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_hubConnection.On<string>("FriendRequestReceived", (message) => // Assuming message is a simple string notification
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\n[Система] Новый запрос в друзья: {message}");
|
||||||
|
Console.Write(CurrentChatUser == null ? "/> " : ">> ");
|
||||||
|
});
|
||||||
|
|
||||||
|
_hubConnection.On<string>("FriendRequestAccepted", (message) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\n[Система] Ваш запрос в друзья принят: {message}");
|
||||||
|
Console.Write(CurrentChatUser == null ? "/> " : ">> ");
|
||||||
|
});
|
||||||
|
|
||||||
|
_hubConnection.On<string>("FriendRemoved", (message) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\n[Система] Пользователь удалил вас из друзей или вы удалили его: {message}");
|
||||||
|
Console.Write(CurrentChatUser == null ? "/> " : ">> ");
|
||||||
|
});
|
||||||
|
|
||||||
|
_hubConnection.On<string>("UserBlocked", (message) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\n[Система] Пользователь заблокирован: {message}");
|
||||||
|
Console.Write(CurrentChatUser == null ? "/> " : ">> ");
|
||||||
|
});
|
||||||
|
_hubConnection.On<string>("UserUnblocked", (message) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\n[Система] Пользователь разблокирован: {message}");
|
||||||
|
Console.Write(CurrentChatUser == null ? "/> " : ">> ");
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _hubConnection.StartAsync();
|
await _hubConnection.StartAsync();
|
||||||
@@ -280,8 +287,9 @@ namespace Govor.ConsoleClient
|
|||||||
{
|
{
|
||||||
if (AuthToken == null) return Guid.Empty;
|
if (AuthToken == null) return Guid.Empty;
|
||||||
var handler = new JwtSecurityTokenHandler();
|
var handler = new JwtSecurityTokenHandler();
|
||||||
|
if (!handler.CanReadToken(AuthToken)) return Guid.Empty;
|
||||||
var jwtToken = handler.ReadJwtToken(AuthToken);
|
var jwtToken = handler.ReadJwtToken(AuthToken);
|
||||||
var userIdClaim = jwtToken.Claims.FirstOrDefault(claim => claim.Type == "userId");
|
var userIdClaim = jwtToken.Claims.FirstOrDefault(claim => claim.Type == "userId" || claim.Type == System.Security.Claims.ClaimTypes.NameIdentifier);
|
||||||
return userIdClaim != null && Guid.TryParse(userIdClaim.Value, out var userId) ? userId : Guid.Empty;
|
return userIdClaim != null && Guid.TryParse(userIdClaim.Value, out var userId) ? userId : Guid.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,22 +299,24 @@ namespace Govor.ConsoleClient
|
|||||||
Console.Clear();
|
Console.Clear();
|
||||||
Console.WriteLine($"/*====================================");
|
Console.WriteLine($"/*====================================");
|
||||||
Console.WriteLine($" * Личные сообщения | {user} ({CurrentChatUserId})");
|
Console.WriteLine($" * Личные сообщения | {user} ({CurrentChatUserId})");
|
||||||
|
Console.WriteLine($" * (/back для выхода из чата)");
|
||||||
Console.WriteLine($" *====================================");
|
Console.WriteLine($" *====================================");
|
||||||
|
|
||||||
if (!ChatHistory.ContainsKey(user))
|
if (!ChatHistory.ContainsKey(user))
|
||||||
{
|
{
|
||||||
ChatHistory[user] = new List<string>();
|
ChatHistory[user] = new List<string>();
|
||||||
// Example initial messages - consider fetching history if implementing that
|
// Potentially load chat history here via an API call if desired
|
||||||
// ChatHistory[user].Add($"[Система] Начало чата с {user}");
|
// ChatHistory[user].Add($"[Система] Начало чата с {user}. Введите сообщение или /back.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var msg in ChatHistory[user])
|
||||||
|
Console.WriteLine(" * " + msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var msg in ChatHistory[user])
|
|
||||||
Console.WriteLine(" * " + msg);
|
|
||||||
|
|
||||||
Console.WriteLine(" *------------------------------------");
|
Console.WriteLine(" *------------------------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
static async void SendMessage(string messageContent)
|
static async Task SendMessageAsync(string messageContent)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(messageContent) || _hubConnection == null || CurrentChatUserId == Guid.Empty) return;
|
if (string.IsNullOrWhiteSpace(messageContent) || _hubConnection == null || CurrentChatUserId == Guid.Empty) return;
|
||||||
|
|
||||||
@@ -320,24 +330,23 @@ namespace Govor.ConsoleClient
|
|||||||
var messageRequest = new MessageRequest
|
var messageRequest = new MessageRequest
|
||||||
{
|
{
|
||||||
RecipientId = CurrentChatUserId,
|
RecipientId = CurrentChatUserId,
|
||||||
EncryptedContent = messageContent, // Assuming content is not actually encrypted for console client simplicity for now
|
EncryptedContent = messageContent,
|
||||||
RecipientType = RecipientType.User,
|
RecipientType = RecipientType.User,
|
||||||
// MediaAttachments and ReplyToMessageId can be added if needed
|
|
||||||
};
|
};
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _hubConnection.InvokeAsync("Send", messageRequest);
|
await _hubConnection.InvokeAsync("Send", messageRequest);
|
||||||
|
|
||||||
// Add to local history immediately for responsiveness.
|
|
||||||
// Server will send "ReceiveMessage" to self as well if needed, or "MessageSent" for confirmation.
|
|
||||||
var displayMessage = $"[{DateTime.Now:HH:mm}] Ты >> {messageContent}";
|
var displayMessage = $"[{DateTime.Now:HH:mm}] Ты >> {messageContent}";
|
||||||
if (!ChatHistory.ContainsKey(CurrentChatUser!))
|
if (!ChatHistory.ContainsKey(CurrentChatUser!))
|
||||||
{
|
{
|
||||||
ChatHistory[CurrentChatUser!] = new List<string>();
|
ChatHistory[CurrentChatUser!] = new List<string>();
|
||||||
}
|
}
|
||||||
ChatHistory[CurrentChatUser!].Add(displayMessage);
|
ChatHistory[CurrentChatUser!].Add(displayMessage);
|
||||||
// Console.WriteLine($"Ты >> {messageContent}"); // Already handled by input echo + ReceiveMessage from self
|
// No Console.WriteLine here, message will be echoed by "ReceiveMessage" if server sends it to self,
|
||||||
|
// or we rely on user seeing their own typed message.
|
||||||
|
// The ReceiveMessage handler should ideally handle self-messages for consistent display.
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -352,12 +361,14 @@ namespace Govor.ConsoleClient
|
|||||||
Console.WriteLine($" *====================================");
|
Console.WriteLine($" *====================================");
|
||||||
Console.WriteLine(" * /reg - создать аккаунт ");
|
Console.WriteLine(" * /reg - создать аккаунт ");
|
||||||
Console.WriteLine(" * /login - войти");
|
Console.WriteLine(" * /login - войти");
|
||||||
|
Console.WriteLine(" * /help - список команд");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoginResponse class was here, can be removed if not used elsewhere or moved to a Contracts project.
|
||||||
public class LoginResponse
|
// Assuming it's implicitly handled by HttpClientService or was specific to the old Program.cs structure.
|
||||||
{
|
// public class LoginResponse
|
||||||
public string token { get; set; }
|
// {
|
||||||
}
|
// public string token { get; set; }
|
||||||
|
// }
|
||||||
Reference in New Issue
Block a user