Skip to content

Commit

Permalink
Update to v0.1.0-rc2 (#40)
Browse files Browse the repository at this point in the history
* Handle IOException separately in ApiProcedures

Caught IOException explicitly to provide more granular error handling. This allows to throw the IOException immediately while preserving the behavior for general exceptions. Adjusted throttler release comment to remove redundant text.

* Enable output redirection in ApiProcedures

This commit updates the process start information in ApiProcedures.cs to redirect standard output and error. It also sets UseShellExecute to false and CreateNoWindow to true for better process control and visibility.

* Merge pull request #37

* Add support for bug tracking and enhance profile management
* Add ability to change installation directory dynamically

* Enhance path handling with Path.GetFullPath()

Updated the SystemIOProcedures helper to use Path.GetFullPath for constructing and validating paths. This ensures absolute references, thereby enhancing path accuracy and security checks when manipulating directories and files.

* Add OAuth token authentication method

Implement a new authentication method using OAuth tokens across several classes to enhance security. This method allows users to authenticate using an access token, improving the flexibility and modernizing the authentication process.

* Add ProcessHelper to handle process module monitoring

Introduce ProcessHelper with a StartWatch method to observe and log module changes of a given process. This implementation uses reactive extensions to handle the monitoring and provides module addition and removal logging.

* Prevent overwriting files larger than 100MB.

Added a size check to skip overwriting files that are 100MB or larger in the `SystemIOProcedures` class. This change ensures large files are not unnecessarily replaced, optimizing performance and avoiding potential issues with large file handling.

* Fix potential crash in ProfileFileWatcher process termination

Ensure the process has not exited before attempting to kill it to prevent an InvalidOperationException. Added a try-catch block to safely handle exceptions if the process termination fails.

* Add README for Gml.Client setup and development

Created a comprehensive README guide for the Gml.Client project. It includes step-by-step instructions for cloning, setting up, building, running, and publishing the project, as well as contributing guidelines and additional resources.

---------

Co-authored-by: Akemiko <[email protected]>
Co-authored-by: GamerVII-NET <[email protected]>
  • Loading branch information
3 people authored Oct 12, 2024
1 parent 2c66ab4 commit eacbbb5
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 3 deletions.
86 changes: 86 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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
<TargetFramework>net8.0</TargetFramework>
```

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!
17 changes: 17 additions & 0 deletions src/Gml.Client/GmlClientManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,23 @@ public async Task DownloadNotInstalledFiles(ProfileReadInfoDto profileInfo,
return user;
}

public async Task<(IUser User, string Message, IEnumerable<string> 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);
Expand Down
33 changes: 33 additions & 0 deletions src/Gml.Client/Helpers/ApiProcedures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,39 @@ public static async Task<string> GetSentryLink(string hostUrl)
return (authUser, dto?.Message ?? string.Empty, dto?.Errors ?? []);
}

public async Task<(IUser User, string Message, IEnumerable<string> 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<ResponseMessage<PlayerReadDto>>(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<string>());
}

return (authUser, dto?.Message ?? string.Empty, dto?.Errors ?? []);
}

public async Task DownloadFiles(string installationDirectory, ProfileFileReadDto[] files, int loadFilesPartCount,
CancellationToken cancellationToken = default)
{
Expand Down
20 changes: 20 additions & 0 deletions src/Gml.Client/Helpers/ProcessHelper.cs
Original file line number Diff line number Diff line change
@@ -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<ProcessModule>()
.ToObservable()
.Subscribe(module => Console.WriteLine($"Module added: {module}"), () => Console.WriteLine("A module was removed"));
}
}
11 changes: 9 additions & 2 deletions src/Gml.Client/Helpers/ProfileFileWatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
}
}
8 changes: 7 additions & 1 deletion src/Gml.Client/Helpers/SystemIOProcedures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -37,14 +38,19 @@ public List<ProfileFileReadDto> FindErroneousFiles(

if (FileExists(localPath))
{
if (new FileInfo(localPath).Length >= _oneHundredMB)
{
return;
}

var hashIsCorrect = SystemHelper.CalculateFileHash(localPath, new SHA256Managed()) == downloadingFile.Hash;
if (hashIsCorrect)
{
return;
}
}

if (!FileExists(localPath) || !whiteListFiles.Any(c => c.Hash.Equals(downloadingFile.Hash)))
if (!whiteListFiles.Any(c => c.Hash.Equals(downloadingFile.Hash)))
{
errorFiles.Add(downloadingFile);
}
Expand Down
1 change: 1 addition & 0 deletions src/Gml.Client/IGmlClientManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public interface IGmlClientManager : IDisposable
public Task<Process> GetProcess(ProfileReadInfoDto profileDto, OsType osType);
Task DownloadNotInstalledFiles(ProfileReadInfoDto profileInfo, CancellationToken cancellationToken);
Task<(IUser User, string Message, IEnumerable<string> Details)> Auth(string login, string password, string hwid);
Task<(IUser User, string Message, IEnumerable<string> Details)> Auth(string accessToken);
Task ClearFiles(ProfileReadInfoDto profile);
Task LoadDiscordRpc();
Task UpdateDiscordRpcState(string state);
Expand Down
1 change: 1 addition & 0 deletions src/Gml.Web.Api.Dto/User/BaseUserPassword.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ public class BaseUserPassword
{
public string Login { get; set; }
public string Password { get; set; }
public string AccessToken { get; set; }
}

0 comments on commit eacbbb5

Please sign in to comment.