mirror of
https://github.com/Govor-team/Govor.git
synced 2026-07-21 19:54:55 +00:00
rework console client
This commit is contained in:
@@ -27,8 +27,4 @@
|
|||||||
<ProjectReference Include="..\Govor.API\Govor.API.csproj" />
|
<ProjectReference Include="..\Govor.API\Govor.API.csproj" />
|
||||||
<ProjectReference Include="..\Govor.Data\Govor.Data.csproj" />
|
<ProjectReference Include="..\Govor.Data\Govor.Data.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="IntegrationTests\EF\Repositories\" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -87,15 +87,15 @@ public class ChatsHub : Hub
|
|||||||
|
|
||||||
public async Task Send(MessageRequest request)
|
public async Task Send(MessageRequest request)
|
||||||
{
|
{
|
||||||
|
var senderId = GetUserId();
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(request.EncryptedContent) &&
|
if (string.IsNullOrWhiteSpace(request.EncryptedContent) &&
|
||||||
(request.MediaAttachments == null || !request.MediaAttachments.Any()))
|
(request.MediaAttachments == null || !request.MediaAttachments.Any()))
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Empty message (no content and no attachments) received from user {UserId}",
|
_logger.LogWarning("Empty message (no content and no attachments) received from user {UserId}", senderId);
|
||||||
GetUserId());
|
|
||||||
throw new ArgumentException("Message cannot be empty (must have content or attachments).");
|
throw new ArgumentException("Message cannot be empty (must have content or attachments).");
|
||||||
}
|
}
|
||||||
|
|
||||||
var senderId = GetUserId();
|
|
||||||
_logger.LogInformation("Message send initiated by {SenderId} to {RecipientId} of type {RecipientType}",
|
_logger.LogInformation("Message send initiated by {SenderId} to {RecipientId} of type {RecipientType}",
|
||||||
senderId, request.RecipientId, request.RecipientType);
|
senderId, request.RecipientId, request.RecipientType);
|
||||||
|
|
||||||
@@ -153,6 +153,69 @@ public class ChatsHub : Hub
|
|||||||
|
|
||||||
public async Task Remove(RemoveMessageRequest request)
|
public async Task Remove(RemoveMessageRequest request)
|
||||||
{
|
{
|
||||||
|
var removerId = GetUserId();
|
||||||
|
_logger.LogInformation("Message removal initiated by {RemoverId} for message {MessageId}", removerId, request.MessageId);
|
||||||
|
|
||||||
|
var removeParams = new DeleteMessage(
|
||||||
|
DeleterId: removerId,
|
||||||
|
MessageId: request.MessageId
|
||||||
|
);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await _messageCommandService.DeleteMessageAsync(removeParams);
|
||||||
|
if (!result.IsSuccess)
|
||||||
|
{
|
||||||
|
_logger.LogError(result.Exception, "Failed to remove message {MessageId} by {RemoverId}. Error: {ErrorMessage}", request.MessageId, removerId, result.Exception?.Message ?? "Unknown error");
|
||||||
|
if (result.Exception != null) throw result.Exception;
|
||||||
|
throw new HubException("Failed to remove message.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var originalMessage = result.OriginalMessage; // Assuming service returns this
|
||||||
|
if (originalMessage == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("DeleteMessageAsync succeeded but did not return the original message details for message {MessageId}", request.MessageId);
|
||||||
|
throw new HubException("Failed to process message deletion due to missing message details.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var removalNotification = new MessageRemovedResponse
|
||||||
|
{
|
||||||
|
MessageId = request.MessageId,
|
||||||
|
SenderId = originalMessage.SenderId,
|
||||||
|
RecipientId = originalMessage.RecipientId,
|
||||||
|
RecipientType = originalMessage.RecipientType
|
||||||
|
};
|
||||||
|
|
||||||
|
// Notify relevant clients
|
||||||
|
if (originalMessage.RecipientType == RecipientType.User)
|
||||||
|
{
|
||||||
|
await Clients.Group(originalMessage.SenderId.ToString()).SendAsync("MessageRemoved", removalNotification);
|
||||||
|
if (originalMessage.SenderId != originalMessage.RecipientId)
|
||||||
|
{
|
||||||
|
await Clients.Group(originalMessage.RecipientId.ToString()).SendAsync("MessageRemoved", removalNotification);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (originalMessage.RecipientType == RecipientType.Group)
|
||||||
|
{
|
||||||
|
await Clients.Group($"group_{originalMessage.RecipientId}").SendAsync("MessageRemoved", removalNotification);
|
||||||
|
}
|
||||||
|
_logger.LogInformation("Message {MessageId} removed successfully by {RemoverId}", request.MessageId, removerId);
|
||||||
|
}
|
||||||
|
catch (UnauthorizedAccessException ex)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Unauthorized attempt to remove message {MessageId} by user {RemoverId}", request.MessageId, removerId);
|
||||||
|
throw new HubException("You are not authorized to remove this message.", ex);
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException ex) // Or a custom NotFoundException
|
||||||
|
{
|
||||||
|
_logger.LogWarning(ex, "Attempt to remove non-existent message {MessageId} by user {RemoverId}", request.MessageId, removerId);
|
||||||
|
throw new HubException("Message not found.", ex);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error removing message {MessageId} by {RemoverId}", request.MessageId, removerId);
|
||||||
|
throw new HubException("An error occurred while removing the message.", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Edit(EditMessageRequest request)
|
public async Task Edit(EditMessageRequest request)
|
||||||
|
|||||||
@@ -121,8 +121,8 @@ app.UseAuthorization();
|
|||||||
|
|
||||||
app.MapControllers();
|
app.MapControllers();
|
||||||
|
|
||||||
app.MapHub<ChatsHub>("/api/chats");
|
app.MapHub<ChatsHub>("/hubs/friends");
|
||||||
app.MapHub<FriendsHub>("/api/friends");
|
app.MapHub<FriendsHub>("/hubs/friends");
|
||||||
|
|
||||||
app.MapSwagger().RequireAuthorization();
|
app.MapSwagger().RequireAuthorization();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
|
|
||||||
namespace Govor.ConsoleClient.Commands
|
namespace Govor.ConsoleClient.Commands
|
||||||
{
|
{
|
||||||
@@ -24,7 +25,7 @@ namespace Govor.ConsoleClient.Commands
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// API uses Hub for this: AcceptFriendRequest(Guid friendshipId)
|
// API uses Hub for this: AcceptFriendRequest(Guid friendshipId)
|
||||||
await HubConnection.InvokeAsync("AcceptFriendRequest", friendshipId);
|
await HubConnection.InvokeAsync("AcceptRequest", friendshipId);
|
||||||
Console.WriteLine("Заявка в друзья принята.");
|
Console.WriteLine("Заявка в друзья принята.");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Govor.Contracts.DTOs; // Required for FriendshipDto
|
using Govor.Contracts.DTOs; // Required for FriendshipDto
|
||||||
|
|
||||||
@@ -19,15 +20,12 @@ namespace Govor.ConsoleClient.Commands
|
|||||||
Console.WriteLine("Получение всех дружеских связей (только для администраторов)...");
|
Console.WriteLine("Получение всех дружеских связей (только для администраторов)...");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var response = await HttpClientService.GetAsync("api/admin/Friendships");
|
var json = 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>>();
|
var friendships = JsonSerializer.Deserialize<List<FriendshipDto>>(json, new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
PropertyNameCaseInsensitive = true
|
||||||
|
});
|
||||||
|
|
||||||
if (friendships != null && friendships.Any())
|
if (friendships != null && friendships.Any())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Govor.Contracts.DTOs; // Required for FriendshipDto
|
using Govor.Contracts.DTOs; // Required for FriendshipDto
|
||||||
|
|
||||||
@@ -30,14 +31,8 @@ namespace Govor.ConsoleClient.Commands
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var response = await HttpClientService.GetAsync($"api/admin/Friendships/{userId}");
|
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>>();
|
var friendships = JsonSerializer.Deserialize<List<FriendshipDto>>(response);
|
||||||
|
|
||||||
if (friendships != null && friendships.Any())
|
if (friendships != null && friendships.Any())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,13 +33,6 @@ namespace Govor.ConsoleClient.Commands
|
|||||||
|
|
||||||
var response = await HttpClientService.PostAsync($"api/admin/Friendships?Id={friendshipId}", null);
|
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} успешно удалена.");
|
Console.WriteLine($"Дружеская связь {friendshipId} успешно удалена.");
|
||||||
}
|
}
|
||||||
catch (HttpRequestException httpEx) when (httpEx.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
catch (HttpRequestException httpEx) when (httpEx.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@@ -6,13 +7,13 @@ namespace Govor.ConsoleClient.Commands
|
|||||||
public abstract class BaseCommand : ICommand
|
public abstract class BaseCommand : ICommand
|
||||||
{
|
{
|
||||||
protected static FriendsClient? FriendsClient { get; private set; }
|
protected static FriendsClient? FriendsClient { get; private set; }
|
||||||
protected static HttpClientService HttpClientService { get; private set; }
|
protected static HttpClientService HttpClientService { get; private set; } = null!;
|
||||||
protected static Func<string?> GetAuthToken { get; private set; }
|
protected static Func<string?> GetAuthToken { get; private set; } = null!;
|
||||||
protected static Action<string> SetAuthToken { get; private set; }
|
protected static Action<string> SetAuthToken { get; private set; } = null!;
|
||||||
protected static Func<Task> InitializeHubConnectionAsync { get; private set; }
|
protected static Func<Task> InitializeHubConnectionAsync { get; private set; } = null!;
|
||||||
protected static Microsoft.AspNetCore.SignalR.Client.HubConnection? HubConnection => _hubConnection?.Invoke();
|
protected static HubConnection HubConnection => _getHubConnection?.Invoke();
|
||||||
private static Func<Microsoft.AspNetCore.SignalR.Client.HubConnection?> _hubConnection;
|
|
||||||
|
|
||||||
|
private static Func<HubConnection?> _getHubConnection = null!;
|
||||||
|
|
||||||
public static void InitializeServices(
|
public static void InitializeServices(
|
||||||
FriendsClient? friendsClient,
|
FriendsClient? friendsClient,
|
||||||
@@ -20,43 +21,42 @@ namespace Govor.ConsoleClient.Commands
|
|||||||
Func<string?> getAuthToken,
|
Func<string?> getAuthToken,
|
||||||
Action<string> setAuthToken,
|
Action<string> setAuthToken,
|
||||||
Func<Task> initializeHubConnectionAsync,
|
Func<Task> initializeHubConnectionAsync,
|
||||||
Func<Microsoft.AspNetCore.SignalR.Client.HubConnection?> hubConnection)
|
Func<HubConnection?> getHubConnection)
|
||||||
{
|
{
|
||||||
FriendsClient = friendsClient;
|
FriendsClient = friendsClient;
|
||||||
HttpClientService = httpClientService;
|
HttpClientService = httpClientService;
|
||||||
GetAuthToken = getAuthToken;
|
GetAuthToken = getAuthToken;
|
||||||
SetAuthToken = setAuthToken;
|
SetAuthToken = setAuthToken;
|
||||||
InitializeHubConnectionAsync = initializeHubConnectionAsync;
|
InitializeHubConnectionAsync = initializeHubConnectionAsync;
|
||||||
_hubConnection = hubConnection;
|
_getHubConnection = getHubConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Task ExecuteAsync(string? argument);
|
public abstract Task ExecuteAsync(string? argument);
|
||||||
public abstract string GetHelp();
|
public abstract string GetHelp();
|
||||||
|
|
||||||
protected boolEnsureLoggedIn()
|
protected bool EnsureLoggedIn()
|
||||||
{
|
{
|
||||||
if (GetAuthToken() == null)
|
if (GetAuthToken() == null)
|
||||||
{
|
{
|
||||||
System.Console.WriteLine("[Ошибка] Сначала войдите в систему. Используйте /login или /reg.");
|
Console.WriteLine("[Ошибка] Сначала войдите в систему. Используйте /login или /reg.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (FriendsClient == null && !(this is LoginCommand || this is RegisterCommand)) // FriendsClient might not be needed for auth commands
|
|
||||||
|
if (FriendsClient == null && !(this is LoginCommand || this is RegisterCommand))
|
||||||
{
|
{
|
||||||
// Attempt to re-initialize FriendsClient if token exists but client is null
|
Console.WriteLine("[Ошибка] Клиент для работы с друзьями не инициализирован. Попробуйте войти снова.");
|
||||||
// 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 false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolEnsureHubConnection()
|
protected bool EnsureHubConnection()
|
||||||
{
|
{
|
||||||
if (HubConnection == null || HubConnection.State != Microsoft.AspNetCore.SignalR.Client.HubConnectionState.Connected)
|
var hub = _getHubConnection?.Invoke();
|
||||||
|
if (hub == null || hub.State != HubConnectionState.Connected)
|
||||||
{
|
{
|
||||||
System.Console.WriteLine("[Ошибка] SignalR соединение не установлено. Попробуйте войти снова или проверьте соединение.");
|
Console.WriteLine("[Ошибка] SignalR соединение не установлено. Попробуйте войти снова или проверьте соединение.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
|
|
||||||
namespace Govor.ConsoleClient.Commands
|
namespace Govor.ConsoleClient.Commands
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Govor.Contracts.DTOs; // Required for FriendshipDto
|
using Govor.Contracts.DTOs; // Required for FriendshipDto
|
||||||
|
|
||||||
@@ -17,10 +18,12 @@ namespace Govor.ConsoleClient.Commands
|
|||||||
{
|
{
|
||||||
// This functionality maps to GET api/friends/responses in FriendsRequestQueryController
|
// This functionality maps to GET api/friends/responses in FriendsRequestQueryController
|
||||||
// FriendsClient doesn't have a dedicated method, so we use HttpClientService or direct HttpClient
|
// FriendsClient doesn't have a dedicated method, so we use HttpClientService or direct HttpClient
|
||||||
var response = await HttpClientService.GetAsync("api/friends/responses");
|
var json = await HttpClientService.GetAsync("api/friends/responses");
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
var requests = await response.Content.ReadFromJsonAsync<System.Collections.Generic.List<FriendshipDto>>();
|
var requests = JsonSerializer.Deserialize<List<FriendshipDto>>(json, new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
PropertyNameCaseInsensitive = true
|
||||||
|
});
|
||||||
|
|
||||||
if (requests != null && requests.Any())
|
if (requests != null && requests.Any())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -30,8 +30,9 @@ namespace Govor.ConsoleClient.Commands
|
|||||||
sharedClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
|
sharedClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
|
||||||
var friendsClient = new FriendsClient(sharedClient);
|
var friendsClient = new FriendsClient(sharedClient);
|
||||||
|
|
||||||
// Re-initialize services in BaseCommand with the new FriendsClient
|
|
||||||
InitializeServices(friendsClient, HttpClientService, GetAuthToken, SetAuthToken, InitializeHubConnectionAsync, HubConnection);
|
|
||||||
|
Program.UpdateFriendsClient(friendsClient); // <-- единственный нужный вызов
|
||||||
|
|
||||||
await InitializeHubConnectionAsync();
|
await InitializeHubConnectionAsync();
|
||||||
Console.WriteLine("[Успех] Вход выполнен. Токен сохранен.");
|
Console.WriteLine("[Успех] Вход выполнен. Токен сохранен.");
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace Govor.ConsoleClient.Commands
|
|||||||
var friendsClient = new FriendsClient(sharedClient);
|
var friendsClient = new FriendsClient(sharedClient);
|
||||||
|
|
||||||
// Re-initialize services in BaseCommand with the new FriendsClient
|
// Re-initialize services in BaseCommand with the new FriendsClient
|
||||||
InitializeServices(friendsClient, HttpClientService, GetAuthToken, SetAuthToken, InitializeHubConnectionAsync, HubConnection);
|
Program.UpdateFriendsClient(friendsClient); // <-- единственный нужный вызов
|
||||||
|
|
||||||
await InitializeHubConnectionAsync();
|
await InitializeHubConnectionAsync();
|
||||||
Console.WriteLine("[Успех] Регистрация завершена. Токен сохранен.");
|
Console.WriteLine("[Успех] Регистрация завершена. Токен сохранен.");
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
|
|
||||||
namespace Govor.ConsoleClient.Commands
|
namespace Govor.ConsoleClient.Commands
|
||||||
{
|
{
|
||||||
@@ -25,7 +26,7 @@ namespace Govor.ConsoleClient.Commands
|
|||||||
{
|
{
|
||||||
// API uses Hub for this: RejectFriendRequest(Guid friendshipId)
|
// API uses Hub for this: RejectFriendRequest(Guid friendshipId)
|
||||||
// Located in Govor.API/Hubs/FriendsHub.cs
|
// Located in Govor.API/Hubs/FriendsHub.cs
|
||||||
await HubConnection.InvokeAsync("RejectFriendRequest", friendshipId);
|
await HubConnection.InvokeAsync("RejectRequest", friendshipId);
|
||||||
Console.WriteLine("Заявка в друзья отклонена.");
|
Console.WriteLine("Заявка в друзья отклонена.");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
|
|
||||||
namespace Govor.ConsoleClient.Commands
|
namespace Govor.ConsoleClient.Commands
|
||||||
{
|
{
|
||||||
@@ -24,7 +25,7 @@ namespace Govor.ConsoleClient.Commands
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// API uses Hub for this: SendFriendRequest(Guid targetUserId)
|
// API uses Hub for this: SendFriendRequest(Guid targetUserId)
|
||||||
await HubConnection.InvokeAsync("SendFriendRequest", targetUserId);
|
await HubConnection.InvokeAsync("SendRequest", targetUserId);
|
||||||
Console.WriteLine("Запрос в друзья отправлен.");
|
Console.WriteLine("Запрос в друзья отправлен.");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
|
|
||||||
namespace Govor.ConsoleClient.Commands
|
namespace Govor.ConsoleClient.Commands
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
|
|
||||||
|
class FriendsHubClient
|
||||||
|
{
|
||||||
|
private readonly HubConnection _connection;
|
||||||
|
|
||||||
|
public FriendsHubClient(string hubUrl, string jwtToken)
|
||||||
|
{
|
||||||
|
_connection = new HubConnectionBuilder()
|
||||||
|
.WithUrl(hubUrl, options =>
|
||||||
|
{
|
||||||
|
options.AccessTokenProvider = () => Task.FromResult(jwtToken);
|
||||||
|
})
|
||||||
|
.WithAutomaticReconnect()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
// Подписка на события от сервера
|
||||||
|
_connection.On<Guid>("FriendRequestReceived", OnFriendRequestReceived);
|
||||||
|
_connection.On<Guid>("FriendRequestAccepted", OnFriendRequestAccepted);
|
||||||
|
_connection.On<Guid>("FriendRequestRejected", OnFriendRequestRejected);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFriendRequestReceived(Guid userId)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Event] Получен запрос в друзья от пользователя: {userId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFriendRequestAccepted(Guid friendshipId)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Event] Запрос в друзья принят. ID дружбы: {friendshipId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFriendRequestRejected(Guid friendshipId)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"[Event] Запрос в друзья отклонён. ID дружбы: {friendshipId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task StartAsync()
|
||||||
|
{
|
||||||
|
await _connection.StartAsync();
|
||||||
|
Console.WriteLine("Подключено к FriendsHub");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task StopAsync()
|
||||||
|
{
|
||||||
|
await _connection.StopAsync();
|
||||||
|
Console.WriteLine("Отключено от FriendsHub");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SendRequest(Guid targetUserId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _connection.InvokeAsync("SendRequest", targetUserId);
|
||||||
|
Console.WriteLine($"Запрос на добавление в друзья отправлен пользователю {targetUserId}");
|
||||||
|
}
|
||||||
|
catch (HubException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Ошибка при отправке запроса: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AcceptRequest(Guid friendshipId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _connection.InvokeAsync("AcceptRequest", friendshipId);
|
||||||
|
Console.WriteLine($"Запрос в друзья с ID {friendshipId} принят");
|
||||||
|
}
|
||||||
|
catch (HubException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Ошибка при принятии запроса: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RejectRequest(Guid friendshipId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _connection.InvokeAsync("RejectRequest", friendshipId);
|
||||||
|
Console.WriteLine($"Запрос в друзья с ID {friendshipId} отклонён");
|
||||||
|
}
|
||||||
|
catch (HubException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Ошибка при отклонении запроса: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static async Task TestMain(string[] args)
|
||||||
|
{
|
||||||
|
// Адрес хаба SignalR
|
||||||
|
string hubUrl = "https://yourserver.com/api/friends";
|
||||||
|
|
||||||
|
// JWT токен для аутентификации (замени на настоящий)
|
||||||
|
string jwtToken = "your_jwt_token_here";
|
||||||
|
|
||||||
|
var client = new FriendsHubClient(hubUrl, jwtToken);
|
||||||
|
|
||||||
|
await client.StartAsync();
|
||||||
|
|
||||||
|
Console.WriteLine("Команды:");
|
||||||
|
Console.WriteLine("send <userId> - Отправить запрос в друзья");
|
||||||
|
Console.WriteLine("accept <friendshipId> - Принять запрос");
|
||||||
|
Console.WriteLine("reject <friendshipId> - Отклонить запрос");
|
||||||
|
Console.WriteLine("exit - Выйти");
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
Console.Write("> ");
|
||||||
|
var input = Console.ReadLine();
|
||||||
|
if (string.IsNullOrWhiteSpace(input))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var parts = input.Split(' ', 2, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
var command = parts[0].ToLowerInvariant();
|
||||||
|
|
||||||
|
if (command == "exit")
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (parts.Length < 2)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Ошибка: не хватает аргументов");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Guid.TryParse(parts[1], out var id))
|
||||||
|
{
|
||||||
|
Console.WriteLine("Ошибка: некорректный GUID");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (command)
|
||||||
|
{
|
||||||
|
case "send":
|
||||||
|
await client.SendRequest(id);
|
||||||
|
break;
|
||||||
|
case "accept":
|
||||||
|
await client.AcceptRequest(id);
|
||||||
|
break;
|
||||||
|
case "reject":
|
||||||
|
await client.RejectRequest(id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine("Неизвестная команда");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await client.StopAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,6 +18,28 @@ namespace Govor.ConsoleClient
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
public async Task<string> RegisterAsync(string username, string password, string inviteCode)
|
||||||
{
|
{
|
||||||
var request = new RegistrationRequest
|
var request = new RegistrationRequest
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using System.Threading.Tasks;
|
|||||||
using Govor.ConsoleClient.Commands;
|
using Govor.ConsoleClient.Commands;
|
||||||
using Govor.Contracts.Requests.SignalR;
|
using Govor.Contracts.Requests.SignalR;
|
||||||
using Govor.Contracts.Responses.SignalR;
|
using Govor.Contracts.Responses.SignalR;
|
||||||
|
using Govor.Core.Models;
|
||||||
|
|
||||||
/*====================================
|
/*====================================
|
||||||
*Личные сообщения| Егор
|
*Личные сообщения| Егор
|
||||||
@@ -194,7 +195,7 @@ namespace Govor.ConsoleClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
_hubConnection = new HubConnectionBuilder()
|
_hubConnection = new HubConnectionBuilder()
|
||||||
.WithUrl($"{baseUrl}/api/chats", options =>
|
.WithUrl($"{baseUrl}/hubs/chats", options =>
|
||||||
{
|
{
|
||||||
options.AccessTokenProvider = () => Task.FromResult(AuthToken);
|
options.AccessTokenProvider = () => Task.FromResult(AuthToken);
|
||||||
})
|
})
|
||||||
@@ -203,7 +204,7 @@ namespace Govor.ConsoleClient
|
|||||||
_hubConnection.On<UserMessageResponse>("ReceiveMessage", (message) =>
|
_hubConnection.On<UserMessageResponse>("ReceiveMessage", (message) =>
|
||||||
{
|
{
|
||||||
var myId = GetMyUserId();
|
var myId = GetMyUserId();
|
||||||
var senderName = message.SenderId == myId ? "Ты" : CurrentChatUser ?? message.SenderUsername ?? "Неизвестно";
|
var senderName = message.SenderId == myId ? "Ты" : CurrentChatUser ?? message.SenderId.ToString() ?? "Неизвестно";
|
||||||
var displayMessage = $"[{message.SentAt:HH:mm}] {senderName} >> {message.EncryptedContent}";
|
var displayMessage = $"[{message.SentAt:HH:mm}] {senderName} >> {message.EncryptedContent}";
|
||||||
|
|
||||||
// Determine chat key based on sender/recipient, ensuring consistency
|
// Determine chat key based on sender/recipient, ensuring consistency
|
||||||
@@ -230,7 +231,7 @@ namespace Govor.ConsoleClient
|
|||||||
}
|
}
|
||||||
else // Notification for message not in the current chat
|
else // Notification for message not in the current chat
|
||||||
{
|
{
|
||||||
Console.WriteLine($"\n[Новое сообщение от {message.SenderUsername ?? message.SenderId.ToString()}]: {message.EncryptedContent}");
|
Console.WriteLine($"\n[Новое сообщение от {message.SenderId.ToString()}]: {message.EncryptedContent}");
|
||||||
Console.Write(CurrentChatUser == null ? "/> " : ">> "); // Re-display prompt
|
Console.Write(CurrentChatUser == null ? "/> " : ">> "); // Re-display prompt
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -331,7 +332,7 @@ namespace Govor.ConsoleClient
|
|||||||
{
|
{
|
||||||
RecipientId = CurrentChatUserId,
|
RecipientId = CurrentChatUserId,
|
||||||
EncryptedContent = messageContent,
|
EncryptedContent = messageContent,
|
||||||
RecipientType = RecipientType.User,
|
RecipientType = RecipientType.User
|
||||||
};
|
};
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using Govor.Core.Models;
|
||||||
|
|
||||||
|
namespace Govor.Contracts.Responses.SignalR;
|
||||||
|
|
||||||
|
public class MessageRemovedResponse
|
||||||
|
{
|
||||||
|
public Guid MessageId { get; set; }
|
||||||
|
public Guid SenderId { get; set; }
|
||||||
|
public Guid RecipientId { get; set; }
|
||||||
|
public RecipientType RecipientType { get; set; }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user