2025-06-19 23:24:39 -07:00

189 lines
7.4 KiB
C#

using Microsoft.AspNetCore.SignalR.Client;
using QtCNETAPI.Dtos.User;
using QtCNETAPI.Events;
using QtCNETAPI.Models;
using QtCNETAPI.Services.ApiService;
namespace QtCNETAPI.Services.GatewayService
{
public class GatewayService : IGatewayService
{
internal string gwBaseUri = "127.0.0.1";
public Room? CurrentRoom { get; private set; }
public bool InLobby { get; private set; }
public HubConnection? HubConnection { get; private set; }
public event EventHandler OnServerMessageReceived;
public event EventHandler OnClientFunctionReceived;
public event EventHandler OnDirectMessageReceived;
public event EventHandler OnServerConfigReceived;
public event EventHandler OnServerDisconnect;
public event EventHandler OnServerReconnecting;
public event EventHandler OnServerReconnected;
private IApiService _apiService;
public GatewayService(string GWUrl, IApiService apiService)
{
gwBaseUri = GWUrl;
_apiService = apiService;
}
public async Task StartAsync()
{
// just to be safe (it doesn't load the server since it shouldn't request a new one unless its actually expired)
await _apiService.RefreshSessionIfInvalid();
// build connection
var gwConBuilder = new HubConnectionBuilder()
.WithAutomaticReconnect()
.WithUrl(gwBaseUri, options =>
{
options.AccessTokenProvider = () => Task.FromResult(_apiService.SessionToken);
});
HubConnection = gwConBuilder.Build();
// start connection
await HubConnection.StartAsync();
// register events
HubConnection.On<string>("rm", (serverMessage) => OnServerMessageReceived?.Invoke(this, new ServerMessageEventArgs{Message = serverMessage}));
HubConnection.On<string>("cf", (function) => OnClientFunctionReceived?.Invoke(this, new ClientFunctionEventArgs{Function = function}));
HubConnection.On<Message, UserInformationDto>("rdm", (message, user) => OnDirectMessageReceived?.Invoke(this, new DirectMessageEventArgs { Message = message, User = user }));
HubConnection.On<ServerConfig>("rc", (serverConfig) => OnServerConfigReceived?.Invoke(this, new ServerConfigEventArgs{ServerConfig = serverConfig}));
HubConnection.Closed += HubConnection_Closed;
HubConnection.Reconnecting += HubConnection_Reconnecting;
HubConnection.Reconnected += HubConnection_Reconnected;
if (HubConnection != null && HubConnection.State == HubConnectionState.Connected)
await HubConnection.SendAsync("l", _apiService.CurrentUser);
}
public async Task StopAsync()
{
if (HubConnection != null && HubConnection.State == HubConnectionState.Connected)
{
await HubConnection.StopAsync();
}
}
public async Task DisposeAsync()
{
if (HubConnection != null && HubConnection.State == HubConnectionState.Disconnected)
{
await HubConnection.DisposeAsync();
HubConnection = null;
CurrentRoom = null;
}
}
public async Task JoinLobbyAsync()
{
await _apiService.RefreshSessionIfInvalid();
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
await HubConnection.SendAsync("jl", _apiService.CurrentUser);
InLobby = true;
CurrentRoom = null;
}
public async Task JoinRoomAsync(Room room)
{
await _apiService.RefreshSessionIfInvalid();
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
if (InLobby == true)
{
await HubConnection.SendAsync("ll", _apiService.CurrentUser);
InLobby = false;
}
else if (CurrentRoom != null)
{
await HubConnection.SendAsync("lr", _apiService.CurrentUser, CurrentRoom);
}
await HubConnection.SendAsync("jr", _apiService.CurrentUser, room);
CurrentRoom = room;
}
public async Task LeaveRoomAsync()
{
await _apiService.RefreshSessionIfInvalid();
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
if (InLobby)
{
await HubConnection.SendAsync("ll", _apiService.CurrentUser);
InLobby = false;
}
else
{
await HubConnection.SendAsync("lr", _apiService.CurrentUser, CurrentRoom);
CurrentRoom = null;
}
}
public async Task RefreshContactsForUser(UserInformationDto user)
{
await _apiService.RefreshSessionIfInvalid();
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
await HubConnection.SendAsync("rcl", user, _apiService.CurrentUser);
}
public async Task PostMessageAsync(Message message)
{
await _apiService.RefreshSessionIfInvalid();
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
await HubConnection.SendAsync("s", _apiService.CurrentUser, message, InLobby, CurrentRoom);
}
public async Task SendDirectMessageAsync(UserInformationDto user, Message message)
{
await _apiService.RefreshSessionIfInvalid();
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
await HubConnection.SendAsync("sdm", _apiService.CurrentUser, user, message);
}
public async Task UpdateStatus(int status)
{
await _apiService.RefreshSessionIfInvalid();
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
await HubConnection.SendAsync("us", _apiService.CurrentUser, status);
}
private Task HubConnection_Closed(Exception? arg)
{
OnServerDisconnect?.Invoke(this, new ServerConnectionClosedEventArgs { Error = arg });
return Task.CompletedTask;
}
private Task HubConnection_Reconnecting(Exception? arg)
{
OnServerReconnecting?.Invoke(this, new ServerConnectionReconnectingEventArgs { Error = arg });
return Task.CompletedTask;
}
private Task HubConnection_Reconnected(string? arg)
{
OnServerReconnected?.Invoke(this, EventArgs.Empty);
return Task.CompletedTask;
}
}
}