Phalcode / gamevault-app

Frontend for the self-hosted gaming platform for drm-free games
https://gamevau.lt
Other
402 stars 18 forks source link

Implemented changes for #144 (command line, custom uri schema & robust client-side api) #360

Closed Zallist closed 8 months ago

Zallist commented 8 months ago

This is in direct response to #144. If this gets pulled through, I'll then probably make a plugin on for Playnite which interacts with it.

I've introduced a Program.cs + Main() entry point which is triggered before any WPF code gets loaded. This is necessary to get access to the command line arguments before they get manipulated, and speed up the response time of custom actions.

Command Line Options are parsed using https://github.com/commandlineparser/commandline which is MIT licensed.

A custom URI handler has been added in the form of gamevault://<action>?parameters, which hooks itself into the Windows Registry to listen globally.

Command Line options, custom URI messages and messages sent via the Named Pipe are all handled with the same CommandOptions base class. So anything that can be done using the command line can also be done by sending a command through the Pipe or by using the gamevault:// uri.

Without modifying the application type away from winexe, it's impossible to actually send messages back to the parent application, so any messages that have to be displayed are displayed in message boxes. The only 2 cases where this is really a problem is when help is called, it'd be a lot simpler to write the help the command line, and it'd also let us respond directly to a Query verb by just writing the result to the output.

Usage

Available actions & params

URI "query" action

When sending a request via URI, an additional action called query is available, which lets you get infromation from the clientside app. This is not a replacement for the server-side backend, and is just a way to get simple information. The specific value to query is provided in the query parameter, with the following available:

Command-line examples

URI examples

Query examples (ensure the main application is running first, expected through the NamedPipe as a message)

C# code to interact with the GameVault app through the named pipe

public static async Task<string> SendPipeMessage(string message, CancellationToken cancellationToken, bool expectsResult = false, int timeout = 500)
{
    string result = null;
    var client = new NamedPipeClientStream("GameVault");
    StreamWriter writer = null;
    StreamReader reader = null;

    try
    {
        await client.ConnectAsync(timeout, cancellationToken);

        writer = new StreamWriter(client, Encoding.UTF8, 1024, leaveOpen: true) { AutoFlush = true };
        await writer.WriteLineAsync(message);

        if (expectsResult)
        {
            reader = new StreamReader(client, Encoding.UTF8, false, 1024, leaveOpen: true);
            result = await reader.ReadLineAsync();
        }
    }
    finally
    {
        SafeDispose(writer);
        SafeDispose(reader);
        SafeDispose(client);
    }

    return result;
}

private static void SafeDispose(IDisposable disposable)
{
    if (disposable == null)
        return;

    try
    {
        disposable.Dispose();
    }
    catch (Exception) { }
}
Yelo420 commented 8 months ago

Hi Zallist, huge thanks for the PR. We appreciate your work very much. We are still preparing for a major change, but we will look at your changes as soon as possible. But at first glance it looks great. Especially the detailed description in the PR.

We get back to you personally. Are you already on our Discord? If not, please join. Communication is a bit easier there.

Then a pro forma question. Have you read and accept the CONTRIBUTING.md?

Zallist commented 8 months ago