Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ReceivedGatewayEvent #2868

Open
wickedmachinator opened this issue Feb 29, 2024 · 5 comments
Open

ReceivedGatewayEvent #2868

wickedmachinator opened this issue Feb 29, 2024 · 5 comments

Comments

@wickedmachinator
Copy link

Hello!

It would be awesome to be able to access DiscordSocketClient.ApiClient, or at least expose an event which gets all events currently handled by DiscordSocketClient.ProcessMessageAsync.

Because everything is internal instead of being protected, I cannot solve this issue without forking Discord.Net.

I will try to add my own ReceivedGatewayEvent eventhandler with reflection to the internal ApiClient property, but even if it works, well, you know... not the best solution. Even the GatewayOpCode enum is internal...

PS: this project is a gemstone of github, congratulations!

@Misha-133
Copy link
Member

Hello!
Thanks for the feedback

Could you better describe your usecase?
Most likely we won't alter the library structure this way in v3 but we are rewriting the library for v4 and we could probably have your usecase addressed there

@wickedmachinator
Copy link
Author

Thank you for the quick answer!

I want to catch all incoming messages from the gateway for debug purposes, better understand of the API, and other stuff.

currently this is not possible:

var client = new DiscordSocketClient(config);
client.ApiClient.ReceivedGatewayEvent += ProcessMessageAsync;

I created a solution to my problem with reflection to be able to add my own message processor to ReceivedGatewayEvent:

    private void AddClientReceivedGatewayEventHandler(DiscordSocketClient client)
    {
        var clientType = client.GetType();
        var apiClientProperty = clientType.GetProperty("ApiClient", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.DeclaredOnly);
        var apiClient = apiClientProperty.GetValue(_client);
        var apiClientType = apiClient.GetType();
        var receivedGatewayEvent = apiClientType.GetEvent("ReceivedGatewayEvent");

        var del = Delegate.CreateDelegate(receivedGatewayEvent.EventHandlerType, this, GetType().GetMethod(nameof(ProcessMessageAsync), System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic));

        receivedGatewayEvent.AddEventHandler(apiClient, del);
    }

    private async Task ProcessMessageAsync(GatewayOpCode opCode, int? sequence, string type, object payload)
    {
        var payloadAsToken = payload as JToken;

        Console.WriteLine(opCode.ToString() + "\t" + (sequence?.ToString() ?? "no sequence") + "\t" + type + "\t" + payloadAsToken?.ToString());
    }

    private enum GatewayOpCode : byte
    {
        .....
    }

You could easily expose a simple event on DiscordSocketClient, with the following parameters
(GatewayOpCode opCode, int? sequence, string type, JToken payload)
or
(GatewayOpCode opCode, int? sequence, string type, object payload)

and invoke this event in DiscordSocketClient.ProcessMessageAsync.

@Misha-133
Copy link
Member

Hm
Thanks for the explanation
I think this is something we can include in v4

@wickedmachinator
Copy link
Author

wickedmachinator commented Feb 29, 2024

one more comment: in Discord.Net.Rest, all model classes are internal. That would be extremely helpful to change them to be public.
If you are worried for "noise", then adding this will solve it:
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]

example:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Discord.API
{
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    public class AuditLogChange
    {
        [JsonProperty("key")]
        public string ChangedProperty { get; set; }

        [JsonProperty("new_value")]
        public JToken NewValue { get; set; }

        [JsonProperty("old_value")]
        public JToken OldValue { get; set; }
    }
}

In this case, we could add low-level gateway message processing via the endpoint requested above, serializing the JToken to the corresponding model, similarly to what DiscordSocketClient.ProcessMessageAsync

I know these are edge-cases, but I can only repeat myself, they would be very useful for advanced processing.

Thank in advance!

@Misha-133
Copy link
Member

Misha-133 commented Feb 29, 2024

That would be extremely helpful to change them to be public.

Yeah, that is planned in v4. All json models will be public

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants