mirror of
https://github.com/Govor-team/Govor.git
synced 2026-07-21 11:44:56 +00:00
42348c863f
Introduces FriendshipsController for admin operations, including listing and removing friendships. Updates routing for admin controllers, improves error handling in UsersController, and enhances FriendsController and related services to include requester details in friendship DTOs. Refactors friend request acceptance to use query parameters and updates console client for improved user feedback and local development configuration.
363 lines
16 KiB
C#
363 lines
16 KiB
C#
using Microsoft.AspNetCore.SignalR.Client;
|
|
using System.IdentityModel.Tokens.Jwt;
|
|
using System.Net.Http.Headers;
|
|
using System.Net.Http.Json;
|
|
using System.Text.Json;
|
|
using Govor.Contracts.Requests;
|
|
using Govor.Contracts.Requests.SignalR;
|
|
using Govor.Contracts.Responses.SignalR;
|
|
using Govor.Core.Models;
|
|
|
|
|
|
/*====================================
|
|
*Личные сообщения| Егор
|
|
*====================================
|
|
* [15:59] Вы добавили (Егор) в друзья
|
|
*
|
|
* [16:30] Егор >> Привет!
|
|
* [16:31] Ты >> Че как?
|
|
*
|
|
*------------------------------------
|
|
* >> "Пойдем завтра гулять?!"
|
|
*/
|
|
|
|
namespace Govor.ConsoleClient
|
|
{
|
|
class Program
|
|
{
|
|
//static string baseUrl = "https://govor-team-govor-88b3.twc1.net";
|
|
static string baseUrl = "https://localhost:7155";
|
|
static string? AuthToken = null;
|
|
static HttpClientService HttpService = new(baseUrl); // поменяй URL на свой
|
|
private static FriendsClient? friendsClient;
|
|
static HubConnection? _hubConnection;
|
|
static Dictionary<string, List<string>> ChatHistory = new();
|
|
static string? CurrentChatUser = null;
|
|
static Guid CurrentChatUserId = Guid.Empty;
|
|
|
|
static async Task Main()
|
|
{
|
|
LoginWindow();
|
|
|
|
while (true)
|
|
{
|
|
Console.Write(CurrentChatUser == null ? "/> " : ">> ");
|
|
var input = Console.ReadLine();
|
|
|
|
if (string.IsNullOrWhiteSpace(input)) continue;
|
|
|
|
if (input.StartsWith("/"))
|
|
HandleCommand(input);
|
|
else if (CurrentChatUser != null)
|
|
SendMessage(input);
|
|
else
|
|
Console.WriteLine("[Система] Введите команду, например /friends");
|
|
}
|
|
}
|
|
|
|
static async void HandleCommand(string input)
|
|
{
|
|
var args = input.Split(' ', 2);
|
|
var command = args[0].ToLower();
|
|
var argument = args.Length > 1 ? args[1] : null;
|
|
|
|
switch (command)
|
|
{
|
|
case "/login":
|
|
Console.Write("username: ");
|
|
var loginUsername = Console.ReadLine();
|
|
|
|
Console.Write("password: ");
|
|
var loginPassword = Console.ReadLine();
|
|
|
|
try
|
|
{
|
|
AuthToken = await HttpService.LoginAsync(loginUsername, loginPassword);
|
|
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 "/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":
|
|
Console.WriteLine("[Система] Выход...");
|
|
if (_hubConnection != null)
|
|
{
|
|
await _hubConnection.StopAsync();
|
|
await _hubConnection.DisposeAsync();
|
|
}
|
|
Environment.Exit(0);
|
|
break;
|
|
|
|
case "/friends":
|
|
if (friendsClient == null)
|
|
{
|
|
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":
|
|
if (friendsClient == null)
|
|
{
|
|
Console.WriteLine("[Ошибка] Сначала войдите в систему.");
|
|
break;
|
|
}
|
|
Console.Write("Введите ID заявки, которую хотите принять принимаете: ");
|
|
var acceptId = Guid.Parse(Console.ReadLine());
|
|
await friendsClient.AcceptFriendRequestAsync(acceptId);
|
|
Console.WriteLine("Принято");
|
|
break;
|
|
case "/incoming":
|
|
if (friendsClient == null)
|
|
{
|
|
Console.WriteLine("[Ошибка] Сначала войдите в систему.");
|
|
break;
|
|
}
|
|
var requests = await friendsClient.GetIncomingRequestsAsync();
|
|
foreach (var r in requests)
|
|
{
|
|
Console.WriteLine($"Запрос от: {r.Requester.Username}| {r.RequesterId} | Был онлайн: {r.Requester.WasOnline} (добавьте через /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))
|
|
{
|
|
Console.WriteLine("[Ошибка] Неверный формат. Укажите имя друга и ID (например /chat Egor GUID)");
|
|
break;
|
|
}
|
|
|
|
CurrentChatUser = chatArgs[0];
|
|
CurrentChatUserId = chatUserId;
|
|
ShowChat(CurrentChatUser);
|
|
break;
|
|
|
|
case "/back":
|
|
CurrentChatUser = null;
|
|
CurrentChatUserId = Guid.Empty;
|
|
break;
|
|
|
|
default:
|
|
Console.WriteLine("[Ошибка] Неизвестная команда");
|
|
break;
|
|
}
|
|
}
|
|
|
|
static async Task InitializeHubConnection()
|
|
{
|
|
if (string.IsNullOrEmpty(AuthToken))
|
|
{
|
|
Console.WriteLine("[Ошибка] Токен аутентификации отсутствует. Пожалуйста, войдите в систему.");
|
|
return;
|
|
}
|
|
|
|
_hubConnection = new HubConnectionBuilder()
|
|
.WithUrl($"{baseUrl}/api/chats", options =>
|
|
{
|
|
options.AccessTokenProvider = () => Task.FromResult(AuthToken);
|
|
})
|
|
.Build();
|
|
|
|
_hubConnection.On<UserMessageResponse>("ReceiveMessage", (message) =>
|
|
{
|
|
var senderName = message.SenderId == GetMyUserId() ? "Ты" : CurrentChatUser ?? "Неизвестно"; // Simplified for now
|
|
var displayMessage = $"[{message.SentAt:HH:mm}] {senderName} >> {message.EncryptedContent}";
|
|
|
|
string chatKey = message.SenderId == GetMyUserId() ? message.RecipientId.ToString() : message.SenderId.ToString();
|
|
|
|
if (CurrentChatUser != null && (message.SenderId == CurrentChatUserId || message.RecipientId == CurrentChatUserId))
|
|
{
|
|
if (!ChatHistory.ContainsKey(CurrentChatUser))
|
|
{
|
|
ChatHistory[CurrentChatUser] = new List<string>();
|
|
}
|
|
ChatHistory[CurrentChatUser].Add(displayMessage);
|
|
Console.SetCursorPosition(0, Console.CursorTop); // Move cursor to beginning of line
|
|
Console.Write(new string(' ', Console.WindowWidth -1)); // Clear current line
|
|
Console.SetCursorPosition(0, Console.CursorTop);
|
|
Console.WriteLine($" * {displayMessage}"); // Display new message
|
|
Console.Write(">> "); // Re-display prompt
|
|
}
|
|
else
|
|
{
|
|
// Handle notification for messages not in the current chat - TBD
|
|
Console.WriteLine($"\n[Новое сообщение от {message.SenderId}]: {message.EncryptedContent}");
|
|
Console.Write(CurrentChatUser == null ? "/> " : ">> ");
|
|
}
|
|
});
|
|
|
|
_hubConnection.On<UserMessageResponse>("MessageSent", (message) =>
|
|
{
|
|
// 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, just logging or ignoring might be fine.
|
|
// Console.WriteLine($"[Система] Сообщение {message.MessageId} доставлено на сервер.");
|
|
});
|
|
|
|
try
|
|
{
|
|
await _hubConnection.StartAsync();
|
|
Console.WriteLine("[SignalR] Соединение установлено.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[SignalR Ошибка] {ex.Message}");
|
|
}
|
|
}
|
|
|
|
static Guid GetMyUserId()
|
|
{
|
|
if (AuthToken == null) return Guid.Empty;
|
|
var handler = new JwtSecurityTokenHandler();
|
|
var jwtToken = handler.ReadJwtToken(AuthToken);
|
|
var userIdClaim = jwtToken.Claims.FirstOrDefault(claim => claim.Type == "userId");
|
|
return userIdClaim != null && Guid.TryParse(userIdClaim.Value, out var userId) ? userId : Guid.Empty;
|
|
}
|
|
|
|
|
|
static void ShowChat(string user)
|
|
{
|
|
Console.Clear();
|
|
Console.WriteLine($"/*====================================");
|
|
Console.WriteLine($" * Личные сообщения | {user} ({CurrentChatUserId})");
|
|
Console.WriteLine($" *====================================");
|
|
|
|
if (!ChatHistory.ContainsKey(user))
|
|
{
|
|
ChatHistory[user] = new List<string>();
|
|
// Example initial messages - consider fetching history if implementing that
|
|
// ChatHistory[user].Add($"[Система] Начало чата с {user}");
|
|
}
|
|
|
|
foreach (var msg in ChatHistory[user])
|
|
Console.WriteLine(" * " + msg);
|
|
|
|
Console.WriteLine(" *------------------------------------");
|
|
}
|
|
|
|
static async void SendMessage(string messageContent)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(messageContent) || _hubConnection == null || CurrentChatUserId == Guid.Empty) return;
|
|
|
|
var myUserId = GetMyUserId();
|
|
if (myUserId == Guid.Empty)
|
|
{
|
|
Console.WriteLine("[Ошибка] Не удалось определить ID пользователя. Попробуйте войти снова.");
|
|
return;
|
|
}
|
|
|
|
var messageRequest = new MessageRequest
|
|
{
|
|
RecipientId = CurrentChatUserId,
|
|
EncryptedContent = messageContent, // Assuming content is not actually encrypted for console client simplicity for now
|
|
RecipientType = RecipientType.User,
|
|
// MediaAttachments and ReplyToMessageId can be added if needed
|
|
};
|
|
|
|
try
|
|
{
|
|
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}";
|
|
if (!ChatHistory.ContainsKey(CurrentChatUser!))
|
|
{
|
|
ChatHistory[CurrentChatUser!] = new List<string>();
|
|
}
|
|
ChatHistory[CurrentChatUser!].Add(displayMessage);
|
|
// Console.WriteLine($"Ты >> {messageContent}"); // Already handled by input echo + ReceiveMessage from self
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"[Ошибка отправки] {ex.Message}");
|
|
}
|
|
}
|
|
|
|
static void LoginWindow()
|
|
{
|
|
Console.WriteLine($"/*====================================");
|
|
Console.WriteLine($" * Добро пожаловать в Govor!");
|
|
Console.WriteLine($" *====================================");
|
|
Console.WriteLine(" * /reg - создать аккаунт ");
|
|
Console.WriteLine(" * /login - войти");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public class LoginResponse
|
|
{
|
|
public string token { get; set; }
|
|
} |