twilight-rs / twilight

Powerful, flexible, and scalable ecosystem of Rust libraries for the Discord API.
https://discord.gg/twilight-rs
ISC License
658 stars 130 forks source link

Unable to deserialize gateway ready event due to missing fields #2216

Closed rksm closed 1 year ago

rksm commented 1 year ago

Hello, I was just testing the hello world example (https://github.com/twilight-rs/twilight/blob/main/examples/gateway-request-members.rs) and ran into an issue with the ready event not being deserializable. twilight expects two fields to be present that were not in my case, the following changes fixed it for me:

diff --git a/twilight-model/src/gateway/payload/incoming/ready.rs b/twilight-model/src/gateway/payload/incoming/ready.rs
index 3808e9d1e7..19e354620b 100644
--- a/twilight-model/src/gateway/payload/incoming/ready.rs
+++ b/twilight-model/src/gateway/payload/incoming/ready.rs
@@ -5,7 +5,8 @@ use serde::{Deserialize, Serialize};

 #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
 pub struct Ready {
-    pub application: PartialApplication,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub application: Option<PartialApplication>,
     pub guilds: Vec<UnavailableGuild>,
     pub resume_gateway_url: String,
     pub session_id: String,
@@ -43,10 +44,10 @@ mod tests {
         ];

         let ready = Ready {
-            application: PartialApplication {
+            application: Some(PartialApplication {
                 flags: ApplicationFlags::empty(),
                 id: Id::new(100),
-            },
+            }),
             guilds,
             resume_gateway_url: "wss://gateway.discord.gg".into(),
             session_id: "foo".to_owned(),
diff --git a/twilight-model/src/guild/unavailable_guild.rs b/twilight-model/src/guild/unavailable_guild.rs
index f4689e53e3..6198e5af91 100644
--- a/twilight-model/src/guild/unavailable_guild.rs
+++ b/twilight-model/src/guild/unavailable_guild.rs
@@ -4,6 +4,7 @@ use serde::{Deserialize, Serialize};
 #[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub struct UnavailableGuild {
     pub id: Id<GuildMarker>,
+    #[serde(default)]
     pub unavailable: bool,
 }

diff --git a/twilight-standby/src/lib.rs b/twilight-standby/src/lib.rs
index c61dbcd2b9..d285811062 100644
--- a/twilight-standby/src/lib.rs
+++ b/twilight-standby/src/lib.rs
@@ -1366,10 +1366,10 @@ mod tests {
     #[tokio::test]
     async fn test_wait_for_event() {
         let ready = Ready {
-            application: PartialApplication {
+            application: Some(PartialApplication {
                 flags: ApplicationFlags::empty(),
                 id: Id::new(1),
-            },
+            }),
             guilds: Vec::new(),
             resume_gateway_url: "wss://gateway.discord.gg".into(),
             session_id: String::new(),
rksm commented 1 year ago

And a similar issue with PRESENCE_UPDATE, missing field guild_id, payload: {"t":"PRESENCE_UPDATE","s":3,"op":0,"d":{"user":{"username":"xyz","id":"123","global_name":null,"discriminator":"3218","avatar_decoration":null,"avatar":"0ed452de979d05d3be21f7a6549ba4ac"},"status":"offline","last_modified":1685661311926,"client_status":{},"broadcast":null,"activities":[]}}

rksm commented 1 year ago

I wasn't able to pinpoint what exact fields needed fixing for the presence update but I got it to work by adding #[serde(default)] to all pub guild_id: Option<Id<GuildMarker>> fields: https://github.com/rksm/twilight/commit/1ac78cb1fca1a402b57940cca174d186e015b88a

rksm commented 1 year ago

And one more: 2023-06-03T01:05:25.614067Z WARN midjourney_api_v2: error receiving event gateway event could not be deserialized: source=missing fieldapplication_idat line 1 column 101, event={"t":"INTERACTION_CREATE","s":3,"op":0,"d":{"nonce":"1664800419089616897","id":"1114359151653568552"}}

It seems the fields token, type and application_id are all optional: https://github.com/rksm/twilight/commit/f5a7f561b8c14908abaed50740c318564a4255a5

Erk- commented 1 year ago

And one more: 2023-06-03T01:05:25.614067Z WARN midjourney_api_v2: error receiving event gateway event could not be deserialized: source=missing fieldapplication_idat line 1 column 101, event={"t":"INTERACTION_CREATE","s":3,"op":0,"d":{"nonce":"1664800419089616897","id":"1114359151653568552"}}

It seems the fields token, type and application_id are all optional: rksm@f5a7f56

Hmm that seems to go against what the documentation tells us https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-structure

rksm commented 1 year ago

For the background, I'm using twilight to interact with the midjourney bot. When posting a new /imagine interaction, the InteractionCreate event that comes back just contains an id and none field. twilight parses this as

InteractionCreate(
    InteractionCreate(
        Interaction {
            app_permissions: None,
            application_id: None,
            channel: None,
            channel_id: None,
            data: None,
            guild_id: None,
            guild_locale: None,
            id: Id<InteractionMarker>(1114365312637337740),
            kind: None,
            locale: None,
            member: None,
            message: None,
            token: None,
            user: None,
        },
    ),
)
Erk- commented 1 year ago

For the background, I'm using twilight to interact with the midjourney bot. When posting a new /imagine interaction, the InteractionCreate event that comes back just contains an id and none field.

Does that mean that you are using it with a user token instead of a bot token?

rksm commented 1 year ago

Yes, I do.

Erk- commented 1 year ago

We generally only support the bot API, any other usage will be largely unsupported. As it is not documented and is against the Terms of Service of Discord.

rksm commented 1 year ago

So what about the remaining deserialization issues?

Erk- commented 1 year ago

So what about the remaining deserialization issues?

Do they happen when you connect with a bot token?

rksm commented 1 year ago

I have no idea but this is about #[serde(default)] annotations of already optional fields. This stuff breaks because those fields are expected but not present.

Erk- commented 1 year ago

Because they are documented to always be present when connecting with a bot user: https://discord.com/developers/docs/topics/gateway-events#ready-ready-event-fields https://discord.com/developers/docs/resources/guild#unavailable-guild-object https://discord.com/developers/docs/topics/gateway-events#presence-update-presence-update-event-fields

If you run into issues while connected with a bot account let us know.

rksm commented 1 year ago

Sorry to hear that. Anyway, thanks for your time.

RedKinda commented 1 year ago

Userbotting is against ToS of both Discord and Midjourney, and is grounds for a permanent ban -signed Midjourney dev

rksm commented 1 year ago

Maybe put a reasonable UI on it then?