diff --git a/README.md b/README.md new file mode 100644 index 0000000..f2153e2 --- /dev/null +++ b/README.md @@ -0,0 +1,86 @@ +# Cloning and Setting Up the Gml.Client Project + +This guide will help you clone the `Gml.Client` project from GitHub, set up the development environment, and publish the +project. + +## Prerequisites + +Before you begin, ensure that you have the following software installed on your machine: + +- [Git](https://git-scm.com/) +- .NET SDK (version 8.0) +- [JetBrains Rider](https://www.jetbrains.com/rider/) + +## Cloning the Repository + +1. Open a terminal. +2. Run the following command to clone the repository: + + ```sh + git clone https://github.com/Gml-Launcher/Gml.Client.git + ``` + +3. Navigate to the project directory: + + ```sh + cd Gml.Client + ``` + +## Setting Up the Development Environment + +1. Open JetBrains Rider. +2. Open the cloned `Gml.Client` project in Rider: + + - Select `Open` from the welcome screen. + - Navigate to the `Gml.Client` project directory and select it. + +3. After the project is loaded, Rider will restore the necessary dependencies. This may take some time. + +## Building the Project + +1. Ensure your project target framework is correctly set to .NET 8.0. You can verify and set the target framework in the + `.csproj` file(s) of your projects: + + ```xml + net8.0 + ``` + +2. Build the project by selecting `Build > Build Solution` from the main menu or by pressing `Ctrl+Shift+B`. + +## Running the Project + +1. Ensure the correct startup configuration is selected (typically the main executable project). +2. Run the project by selecting `Run > Run` from the main menu or by pressing `Shift+F10`. + +## Publishing the Project + +1. Open a terminal. +2. Navigate to the project directory if not already there: + + ```sh + cd Gml.Client + ``` + +3. Run the publish command using the .NET CLI: + + ```sh + dotnet publish -c Release -o ./publish + ``` + + This will publish the project in the `Release` configuration to the `./publish` directory. + +## Contributing + +If you'd like to contribute to the project, please fork the repository and create a pull request. Make sure your code +adheres to the project's coding standards and passes all the tests. + +For any issues or feature requests, you can open an issue on +the [GitHub Issues](https://github.com/Gml-Launcher/Gml.Client/issues) page of the repository. + +## Additional Resources + +- [JetBrains Rider Documentation](https://www.jetbrains.com/help/rider/Introduction.html) +- [.NET Documentation](https://learn.microsoft.com/en-us/dotnet/) + +By following the above steps, you should be able to set up, develop, and publish the `Gml.Client` project successfully. +Happy coding! diff --git a/src/Gml.Client/GmlClientManager.cs b/src/Gml.Client/GmlClientManager.cs index 3878daf..2a578cd 100644 --- a/src/Gml.Client/GmlClientManager.cs +++ b/src/Gml.Client/GmlClientManager.cs @@ -140,6 +140,23 @@ public async Task DownloadNotInstalledFiles(ProfileReadInfoDto profileInfo, return user; } + public async Task<(IUser User, string Message, IEnumerable Details)> Auth(string accessToken) + { + var user = await _apiProcedures.Auth(accessToken); + + if (user.User?.IsAuth == true) + { + if (_launchbackendConnection?.DisposeAsync().AsTask() is {} task) + { + await task; + } + + await OpenServerConnection(user.User); + } + + return user; + } + public async Task OpenServerConnection(IUser user) { _launchbackendConnection = new SignalRConnect($"{_webSocketAddress}/ws/launcher", user); diff --git a/src/Gml.Client/Helpers/ApiProcedures.cs b/src/Gml.Client/Helpers/ApiProcedures.cs index 52c8d08..33522a8 100644 --- a/src/Gml.Client/Helpers/ApiProcedures.cs +++ b/src/Gml.Client/Helpers/ApiProcedures.cs @@ -254,6 +254,39 @@ public static async Task GetSentryLink(string hostUrl) return (authUser, dto?.Message ?? string.Empty, dto?.Errors ?? []); } + public async Task<(IUser User, string Message, IEnumerable Details)> Auth(string accessToken) + { + var model = JsonConvert.SerializeObject(new BaseUserPassword + { + AccessToken = accessToken, + }); + + var authUser = new AuthUser(); + + var data = new StringContent(model, Encoding.UTF8, "application/json"); + var response = await _httpClient.PostAsync("/api/v1/integrations/auth/checkToken", data).ConfigureAwait(false); + _httpClient.DefaultRequestHeaders.Remove("X-HWID"); + authUser.IsAuth = response.IsSuccessStatusCode; + + var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + + var dto = JsonConvert.DeserializeObject>(content); + + if (response.IsSuccessStatusCode && dto != null) + { + authUser.Uuid = dto.Data!.Uuid; + authUser.Name = dto.Data.Name; + authUser.AccessToken = dto.Data!.AccessToken; + authUser.Has2Fa = false; //dto.Data!.Has2Fa; + authUser.ExpiredDate = dto.Data!.ExpiredDate; + authUser.TextureUrl = dto.Data.TextureSkinUrl; + + return (authUser, string.Empty, Enumerable.Empty()); + } + + return (authUser, dto?.Message ?? string.Empty, dto?.Errors ?? []); + } + public async Task DownloadFiles(string installationDirectory, ProfileFileReadDto[] files, int loadFilesPartCount, CancellationToken cancellationToken = default) { diff --git a/src/Gml.Client/Helpers/ProcessHelper.cs b/src/Gml.Client/Helpers/ProcessHelper.cs new file mode 100644 index 0000000..66ecb17 --- /dev/null +++ b/src/Gml.Client/Helpers/ProcessHelper.cs @@ -0,0 +1,20 @@ +using System.Diagnostics; +using System.Reactive; +using System.Reactive.Linq; + +namespace Gml.Client.Helpers; + +public static class ProcessHelper +{ + private static IDisposable? _watchDisposable; + + public static void StartWatch(this Process process) + { + _watchDisposable?.Dispose(); + + _watchDisposable = process.Modules + .Cast() + .ToObservable() + .Subscribe(module => Console.WriteLine($"Module added: {module}"), () => Console.WriteLine("A module was removed")); + } +} diff --git a/src/Gml.Client/Helpers/ProfileFileWatcher.cs b/src/Gml.Client/Helpers/ProfileFileWatcher.cs index dd1af42..5c6fb60 100644 --- a/src/Gml.Client/Helpers/ProfileFileWatcher.cs +++ b/src/Gml.Client/Helpers/ProfileFileWatcher.cs @@ -52,9 +52,16 @@ private void OnNewFileCreated(object sender, FileSystemEventArgs e) FileAdded?.Invoke(this, e.FullPath); - if (_needKill) + if (_needKill && !_process.HasExited) { - _process.Kill(); + try + { + _process.Kill(); + } + catch (InvalidOperationException ex) + { + // Ignore + } } } } diff --git a/src/Gml.Client/Helpers/SystemIOProcedures.cs b/src/Gml.Client/Helpers/SystemIOProcedures.cs index d54b045..eb3c4e6 100644 --- a/src/Gml.Client/Helpers/SystemIOProcedures.cs +++ b/src/Gml.Client/Helpers/SystemIOProcedures.cs @@ -10,6 +10,7 @@ public class SystemIoProcedures { private readonly string _installationDirectory; private readonly OsType _osType; + private const long _oneHundredMB = 100 * 1024 * 1024; public SystemIoProcedures(string installationDirectory, OsType osType) { @@ -37,6 +38,11 @@ public List FindErroneousFiles( if (FileExists(localPath)) { + if (new FileInfo(localPath).Length >= _oneHundredMB) + { + return; + } + var hashIsCorrect = SystemHelper.CalculateFileHash(localPath, new SHA256Managed()) == downloadingFile.Hash; if (hashIsCorrect) { @@ -44,7 +50,7 @@ public List FindErroneousFiles( } } - if (!FileExists(localPath) || !whiteListFiles.Any(c => c.Hash.Equals(downloadingFile.Hash))) + if (!whiteListFiles.Any(c => c.Hash.Equals(downloadingFile.Hash))) { errorFiles.Add(downloadingFile); } diff --git a/src/Gml.Client/IGmlClientManager.cs b/src/Gml.Client/IGmlClientManager.cs index d44e358..68e57b7 100644 --- a/src/Gml.Client/IGmlClientManager.cs +++ b/src/Gml.Client/IGmlClientManager.cs @@ -22,6 +22,7 @@ public interface IGmlClientManager : IDisposable public Task GetProcess(ProfileReadInfoDto profileDto, OsType osType); Task DownloadNotInstalledFiles(ProfileReadInfoDto profileInfo, CancellationToken cancellationToken); Task<(IUser User, string Message, IEnumerable Details)> Auth(string login, string password, string hwid); + Task<(IUser User, string Message, IEnumerable Details)> Auth(string accessToken); Task ClearFiles(ProfileReadInfoDto profile); Task LoadDiscordRpc(); Task UpdateDiscordRpcState(string state); diff --git a/src/Gml.Web.Api.Dto/User/BaseUserPassword.cs b/src/Gml.Web.Api.Dto/User/BaseUserPassword.cs index ba1045e..c696ab5 100644 --- a/src/Gml.Web.Api.Dto/User/BaseUserPassword.cs +++ b/src/Gml.Web.Api.Dto/User/BaseUserPassword.cs @@ -4,4 +4,5 @@ public class BaseUserPassword { public string Login { get; set; } public string Password { get; set; } + public string AccessToken { get; set; } }