discord-net / Discord.Net

An unofficial .Net wrapper for the Discord API (https://discord.com/)
https://discordnet.dev
MIT License
3.32k stars 737 forks source link

[Bug]: Cannot instantiate DiscordWebhookClient #2659

Closed DrHeinzDoofenshmirtz closed 1 year ago

DrHeinzDoofenshmirtz commented 1 year ago

Check The Docs

Verify Issue Source

Check your intents

Description

I am simply trying to instantiate DiscordWebhookClient. No matter which constructor overload I use, I get the error.

Discord.Net throws an ArgumentNullException when trying to read some JSON.

Version

3.10.0

Working Version

No response

Logs

System.ArgumentNullException: Value cannot be null. (Parameter 's')
   at Discord.Net.Converters.UInt64Converter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonSerializer.Deserialize[T](JsonReader reader)
   at Discord.API.DiscordRestApiClient.DeserializeJson[T](Stream jsonStream)
   at Discord.API.DiscordRestApiClient.SendAsync[TResponse](String method, String endpoint, BucketId bucketId, ClientBucketType clientBucket, RequestOptions options)
   at Discord.API.DiscordRestApiClient.GetWebhookAsync(UInt64 webhookId, RequestOptions options)
   at Discord.Webhook.WebhookClientHelper.GetWebhookAsync(DiscordWebhookClient client, UInt64 webhookId)
   at Discord.Webhook.DiscordWebhookClient..ctor(UInt64 webhookId, String webhookToken, DiscordRestConfig config)
   at MathBot.Client.Modules.AvalonModule.Test() in M:\Visual Studio Projects\SirLanceBot\src\SirLanceBot.Client\Modules\AvalonModule.cs:line 140
   at Discord.Interactions.Builders.ModuleClassBuilder.<>c__DisplayClass11_0.<<CreateCallback>g__ExecuteCallback|1>d.MoveNext()

Sample

var webhookClient = new DiscordWebhookClient(
                webhookId: applicationId,
                webhookToken: Context.Interaction.Token);

Both parameters are valid.

Packages

None

DrHeinzDoofenshmirtz commented 1 year ago

Essentially, as I experience it, DiscordWebhookClient is basically useless as it can't even instantiate. I would really like to use it, as it is really nice that it takes care of rate limits.

markski1 commented 1 year ago

Are you sure this json error is caused within DNET? Can you see any more detail in the debugger? I am very mystified by where this 's' null parameter is coming from or what it's trying to parse.

DrHeinzDoofenshmirtz commented 1 year ago

Hi @markski1. Thanks for responding.

I am pretty sure it is from Discord.Net. You can take a look at the stack trace. I can't debug through Discord.Net or the Json library, and honestly I don't understand what the problem is. The reproduction steps are very simple. Do you not get the error?

Matt

exsersewo commented 1 year ago

Are you sure this json error is caused within DNET? Can you see any more detail in the debugger? I am very mystified by where this 's' null parameter is coming from or what it's trying to parse.

s is the string input parameter of type.Parse. For example here's the one for ulong.

This is where the issue is coming from.

I believe a ulong field is nullable when DNET is expecting a value as per the webhook docs application_id, guild_id, and channel_id can all be null. Especially as the stack trace specifically calls GetWebhookAsync from the constructor.

DrHeinzDoofenshmirtz commented 1 year ago

Can any of you recreate the issue?

exsersewo commented 1 year ago

Can't repro, I just get "Could not find a webhook with the supplied credentials".

In the sample above: What is applicationId, your bot's Id? How come you're passing the Interaction Token into the webhook?

DrHeinzDoofenshmirtz commented 1 year ago

Yes, applicationId is the application id of the bot from the developer portal. The webhookToken has confused me a bit. The documentation is very lacking.

As I understand it, it could either refer to the Token of the bot (from the developer portal) for authentication purposes, or it could be the interaction token to be able to reply to specific interactions. If I pass in the token from the developer portal, I get an error that it is not in the correct format. But when using the interaction token I get the error.

I probably completely miss something. I can see why I should pass in the bot token to the webhook client. But I also want to respond to specific interactions, without having to use the socket client. I have been able to do that with simple http calls to the Discord API directly (without using Discord.Net) so I know it is possible. The reason is that I am trying to offload the backend to Azure Functions, so I don't have access to the socket client when I am responding. That is why I need the webhook client.

Another point of confusion is that DiscordWebbookClient can also be initialized with a webhookUrl, which I don't understand how works. Again, the documentation on this is almost non-existent. My goal is to have a webhook client object that can be used to send rich messages (with SendMessageAsync method or similar) directly to the Discord webhook endpoint, to respond to specific interactions. And still taking rate limiting into account for retries and so on.

Thanks for taking the time to help me.

@exsersewo

exsersewo commented 1 year ago

Thanks for confirming those two points.

With now understanding your point, yeah you'd use the interaction token as the webhookToken as only the initial response has a spacial interactions specific endpoint.

Managed to repro it, needed to have originally responded, be it a Defer or Respond.

It's the API Webhook entity not having ChannelId marked as optional.

As here's a sample of what I got back sending a request to https://discord.com/api/v10/webhooks/:applicationid/:interactiontoken in Postman

{
    "type": 3,
    "id": "0123456789",
    "name": "BotName",
    "avatar": "avatarId",
    "channel_id": null,
    "guild_id": null,
    "application_id": "0123456789
}
DrHeinzDoofenshmirtz commented 1 year ago

I understand that you found the problem and the solution. 😊 Is there something I can do in the meanwhile to get it to work, or do I need to wait for a fix?

exsersewo commented 1 year ago

Unfortunately not if you wanted just pure discord.net, as it seems looking around more that webhooks were made with the assumption that channelid would always be set. You could use a third party webhook client for the time being?

DrHeinzDoofenshmirtz commented 1 year ago

So it would be a larger change in Discord.Net to allow ChannelId to be null, because it has been the assumption all over the place? I have a hard time understanding how the DiscordWebhookClient has been implemented, if it presumably has not worked. I am very interested to hear if someone else has it working somehow.

Misha-133 commented 1 year ago

Quite a late response, but it is what it is

Yeah, DNet's webhook model is a bit outdated. I'll make a PR with necessary updates.