From c282473ad519a7f1b1535b32c9a2e76a987c5b79 Mon Sep 17 00:00:00 2001 From: Quat3rnion <81202811+Quat3rnion@users.noreply.github.com> Date: Tue, 21 Jan 2025 15:45:40 -0500 Subject: [PATCH 1/2] Feature/identify bitflags (#595) * Add GatewayIntents and GatewayCapabilities bitflags * Remove unused function definition from SqlxBitFlags macro --- chorus-macros/src/lib.rs | 20 ---- src/types/events/identify.rs | 190 +++++++++++++++++++++++++++++++++-- 2 files changed, 184 insertions(+), 26 deletions(-) diff --git a/chorus-macros/src/lib.rs b/chorus-macros/src/lib.rs index d2797e75..79ee2012 100644 --- a/chorus-macros/src/lib.rs +++ b/chorus-macros/src/lib.rs @@ -183,26 +183,6 @@ pub fn sqlx_bitflag_derive(input: TokenStream) -> TokenStream { >::decode(value).map(|v| Self::from_bits_truncate(v.to_uint())) } } - - /// Converts a [Vec] to an unsigned, 64 bit integer. The [u64] is created using [u64::from_be_bytes]. - /// - /// Empty vectors will result in an output of `0_u64`. Only the first 8 values from the vector are - /// being processed. Any additional values will be skipped. - /// - /// Vectors holding less than 8 values will be treated as a vector holding 8 values, where the - /// missing values are padded with `0_u8`. - fn vec_u8_to_u64(vec: Vec) -> u64 { - let mut buf: [u8; 8] = [0; 8]; - let mut position = 0; - for read in vec.iter() { - buf[position] = *read; - position += 1; - if position > 7 { - break; - } - } - u64::from_be_bytes(buf) - } } .into() } diff --git a/src/types/events/identify.rs b/src/types/events/identify.rs index a248f285..343f173d 100644 --- a/src/types/events/identify.rs +++ b/src/types/events/identify.rs @@ -2,6 +2,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +use bitflags::bitflags; use crate::types::{events::WebSocketEvent, ClientProperties}; use serde::{Deserialize, Serialize}; @@ -24,9 +25,9 @@ pub struct GatewayIdentifyPayload { // Intents is documented, capabilities is used in users // I wonder if these are interchangeable... #[serde(skip_serializing_if = "Option::is_none")] - pub intents: Option, + pub intents: Option, #[serde(skip_serializing_if = "Option::is_none")] - pub capabilities: Option, + pub capabilities: Option, } impl Default for GatewayIdentifyPayload { @@ -39,7 +40,7 @@ impl Default for GatewayIdentifyPayload { shard: None, presence: None, intents: None, - capabilities: None, + capabilities: Some(GatewayCapabilities::default()), } } } @@ -51,7 +52,7 @@ impl GatewayIdentifyPayload { pub fn common() -> Self { Self { properties: ClientProperties::default(), - capabilities: Some(8189), + capabilities: Some(GatewayCapabilities::default()), ..Self::default() } } @@ -59,7 +60,7 @@ impl GatewayIdentifyPayload { /// Creates an identify payload with the same default capabilities as the official client pub fn default_w_client_capabilities() -> Self { Self { - capabilities: Some(8189), // Default capabilities for a client + capabilities: Some(GatewayCapabilities::default()), ..Self::default() } } @@ -67,8 +68,185 @@ impl GatewayIdentifyPayload { /// Creates an identify payload with all possible capabilities pub fn default_w_all_capabilities() -> Self { Self { - capabilities: Some(i32::MAX), // Since discord uses bitwise for capabilities, this has almost every bit as 1, so all capabilities + capabilities: Some(GatewayCapabilities::all()), ..Self::default() } } } + +bitflags! { + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, chorus_macros::SerdeBitFlags)] + #[cfg_attr(feature = "sqlx", derive(chorus_macros::SqlxBitFlags))] + /// # Reference + /// See + pub struct GatewayCapabilities: u64 { + /// Removes the notes field from the Ready event, + const LAZY_USER_NOTES = 1 << 0; + /// Prevents member/presence syncing and Presence Update events for implicit relationships + const NO_AFFINE_USER_IDS = 1 << 1; + /// Enables versioned read states, changing the read_state field in the Ready event to an object, allowing it to be cached when re-identifying + const VERSIONED_READ_STATES = 1 << 2; + /// Enables versioned user guild settings, changing the user_guild_settings field in the Ready event to an object, allowing it to be cached when re-identifying + const VERSIONED_USER_GUILD_SETTINGS = 1 << 3; + /// Dehydrates the Ready payload, moving all user objects to the users field and replacing them in various places in the payload with user_id or recipient_id, and merging the members fields of all guilds into a single merged_members field + const DEDUPE_USER_OBJECTS = 1 << 4; + /// 1 Separates the Ready payload into two parts (Ready and Ready Supplemental) allowing the client to receive the Ready payload faster and then receive the rest of the payload later + const PRIORITIZED_READY_PAYLOAD = 1 << 5; + /// Changes the populations entry of guild_experiments in the Ready event to be an array of populations rather than a single population + const MULTIPLE_GUILD_EXPERIMENT_POPULATIONS = 1 << 6; + /// Includes read states tied to non-channel resources (e.g. guild scheduled events and notification center) in the read_states field of the Ready event + const NON_CHANNEL_READ_STATES = 1 << 7; + /// Enables auth token refresh, allowing the client to optionally receive a new auth token in the auth_token field of the Ready event + const AUTH_TOKEN_REFRESH = 1 << 8; + /// Removes the user_settings field from the Ready event, and prevents User Settings Update events; the user_settings_proto field and User Settings Proto Update event is used instead + const USER_SETTINGS_PROTO = 1 << 9; + /// Enables client state caching v2 + const CLIENT_STATE_V2 = 1 << 10; + /// Enables passive guild updates, allowing the client to receive Passive Update v1 events instead of Channel Unreads Update events for guilds it is not subscribed to + const PASSIVE_GUILD_UPDATE = 1 << 11; + /// Connects the client to all pre-existing calls upon connecting to the Gateway; this means clients will receive Call Create events for all calls created before the Gateway connection was established without needing to send a Request Call Connect first + const AUTO_CALL_CONNECT = 1 << 12; + /// Debounces message reaction events, preventing the client from receiving multiple Message Reaction Add events for the same message within a short period of time; clients will receive a single Message Reaction Add Many event instead + const DEBOUNCE_MESSAGE_REACTIONS = 1 << 13; + /// Enables passive guild updates v2, allowing the client to receive Passive Update v2 events instead of Channel Unreads Update events for guilds it is not subscribed to + const PASSIVE_GUILD_UPDATE_V2 = 1 << 14; + } +} + +impl Default for GatewayCapabilities { + fn default() -> Self { + Self::NO_AFFINE_USER_IDS + | Self::VERSIONED_READ_STATES + | Self::VERSIONED_USER_GUILD_SETTINGS + | Self::DEDUPE_USER_OBJECTS + | Self::PRIORITIZED_READY_PAYLOAD + | Self::MULTIPLE_GUILD_EXPERIMENT_POPULATIONS + | Self::NON_CHANNEL_READ_STATES + | Self::AUTH_TOKEN_REFRESH + | Self::USER_SETTINGS_PROTO + | Self::PASSIVE_GUILD_UPDATE + } +} + +bitflags! { + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, chorus_macros::SerdeBitFlags)] + #[cfg_attr(feature = "sqlx", derive(chorus_macros::SqlxBitFlags))] + /// # Reference + /// See + pub struct GatewayIntents: u64 { + /// - GUILD_CREATE + /// - GUILD_UPDATE + /// - GUILD_DELETE + /// - GUILD_ROLE_CREATE + /// - GUILD_ROLE_UPDATE + /// - GUILD_ROLE_DELETE + /// - CHANNEL_CREATE + /// - CHANNEL_UPDATE + /// - CHANNEL_DELETE + /// - VOICE_CHANNEL_STATUS_UPDATE + /// - CHANNEL_PINS_UPDATE + /// - THREAD_CREATE + /// - THREAD_UPDATE + /// - THREAD_DELETE + /// - THREAD_LIST_SYNC + /// - THREAD_MEMBER_UPDATE + /// - THREAD_MEMBERS_UPDATE ¹ + /// - STAGE_INSTANCE_CREATE + /// - STAGE_INSTANCE_UPDATE + /// - STAGE_INSTANCE_DELETE + const GUILDS = 1 << 0; + /// - GUILD_MEMBER_ADD + /// - GUILD_MEMBER_UPDATE + /// - GUILD_MEMBER_REMOVE + /// - THREAD_MEMBERS_UPDATE ¹ + const GUILD_MEMBERS = 1 << 1; + /// - GUILD_AUDIT_LOG_ENTRY_CREATE + /// - GUILD_BAN_ADD + /// - GUILD_BAN_REMOVE + const GUILD_MODERATION = 1 << 2; + /// - GUILD_EMOJIS_UPDATE + /// - GUILD_STICKERS_UPDATE + const GUILD_EMOJIS_AND_STICKERS = 1 << 3; + /// - GUILD_INTEGRATIONS_UPDATE + /// - INTEGRATION_CREATE + /// - INTEGRATION_UPDATE + /// - INTEGRATION_DELETE + const GUILD_INTEGRATIONS = 1 << 4; + /// - WEBHOOKS_UPDATE + const GUILD_WEBHOOKS = 1 << 5; + /// - INVITE_CREATE + /// - INVITE_DELETE + const GUILD_INVITES = 1 << 6; + /// - VOICE_STATE_UPDATE + /// - VOICE_CHANNEL_EFFECT_SEND + const GUILD_VOICE_STATES = 1 << 7; + /// - PRESENCE_UPDATE + const GUILD_PRESENCES = 1 << 8; + /// - MESSAGE_CREATE + /// - MESSAGE_UPDATE + /// - MESSAGE_DELETE + /// - MESSAGE_DELETE_BULK + const GUILD_MESSAGES = 1 << 9; + /// - MESSAGE_REACTION_ADD + /// - MESSAGE_REACTION_ADD_MANY + /// - MESSAGE_REACTION_REMOVE + /// - MESSAGE_REACTION_REMOVE_ALL + /// - MESSAGE_REACTION_REMOVE_EMOJI + const GUILD_MESSAGE_REACTIONS = 1 << 10; + /// - TYPING_START + const GUILD_MESSAGE_TYPING = 1 << 11; + /// - MESSAGE_CREATE + /// - MESSAGE_UPDATE + /// - MESSAGE_DELETE + /// - CHANNEL_PINS_UPDATE + const DIRECT_MESSAGES = 1 << 12; + /// - MESSAGE_REACTION_ADD + /// - MESSAGE_REACTION_ADD_MANY + /// - MESSAGE_REACTION_REMOVE + /// - MESSAGE_REACTION_REMOVE_ALL + /// - MESSAGE_REACTION_REMOVE_EMOJI + const DIRECT_MESSAGE_REACTIONS = 1 << 13; + /// - TYPING_START + const DIRECT_MESSAGE_TYPING = 1 << 14; + /// Unique privileged intent that isn't directly associated with any Gateway events. Instead, access to MESSAGE_CONTENT permits users to receive message content data across the APIs. + /// # Reference + /// See + const MESSAGE_CONTENT = 1 << 15; + /// - GUILD_SCHEDULED_EVENT_CREATE + /// - GUILD_SCHEDULED_EVENT_UPDATE + /// - GUILD_SCHEDULED_EVENT_DELETE + /// - GUILD_SCHEDULED_EVENT_USER_ADD + /// - GUILD_SCHEDULED_EVENT_USER_REMOVE + const GUILD_SCHEDULE_EVENTS = 1 << 16; + /// - EMBEDDED_ACTIVITY_UPDATE_V2 + const GUILD_EMBEDDED_ACTIVITIES = 1 << 17; + /// - CHANNEL_CREATE + /// - CHANNEL_UPDATE + /// - CHANNEL_DELETE + /// - CHANNEL_RECIPIENT_ADD + /// - CHANNEL_RECIPIENT_REMOVE + const PRIVATE_CHANNELS = 1 << 18; + /// - AUTO_MODERATION_RULE_CREATE + /// - AUTO_MODERATION_RULE_UPDATE + /// - AUTO_MODERATION_RULE_DELETE + const AUTO_MODERATION_CONFIGURATION = 1 << 20; + /// - AUTO_MODERATION_ACTION_EXECUTION + const AUTO_MODERATION_EXECUTION = 1 << 21; + /// - RELATIONSHIP_ADD + /// - RELATIONSHIP_UPDATE + /// - RELATIONSHIP_REMOVE + /// - GAME_RELATIONSHIP_ADD + /// - GAME_RELATIONSHIP_REMOVE + const USER_RELATIONSHIPS = 1 << 22; + /// - PRESENCE_UPDATE + const USER_PRESENCE = 1 << 23; + /// - MESSAGE_POLL_VOTE_ADD + /// - MESSAGE_POLL_VOTE_REMOVE + const GUILD_MESSAGE_POLLS = 1 << 24; + /// - MESSAGE_POLL_VOTE_ADD + /// - MESSAGE_POLL_VOTE_REMOVE + const DIRECT_MESSAGE_POLLS = 1 << 25; + /// - EMBEDDED_ACTIVITY_UPDATE_V2 + const DIRECT_EMBEDDED_ACTIVITES = 1 << 26; + } +} From b40c3acebc818cef8abf7fc0d6e34e34981f8f36 Mon Sep 17 00:00:00 2001 From: kozabrada123 Date: Thu, 23 Jan 2025 15:17:44 +0100 Subject: [PATCH 2/2] fix: skip also when deserializing --- src/types/interfaces/client_properties.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/interfaces/client_properties.rs b/src/types/interfaces/client_properties.rs index 9d549ea3..b8ec01cb 100644 --- a/src/types/interfaces/client_properties.rs +++ b/src/types/interfaces/client_properties.rs @@ -77,7 +77,7 @@ pub struct ClientProperties { /// /// Note that unless connecting to a server you specifically know doesn't care about these /// headers, it is recommended to leave them enabled. - #[serde(skip_serializing)] + #[serde(skip)] pub send_telemetry_headers: bool, /// Always sent, must be provided