diff --git a/src/gateway.rs b/src/gateway.rs index 3ac118d..d3a748c 100644 --- a/src/gateway.rs +++ b/src/gateway.rs @@ -1,8 +1,9 @@ use crate::errors::GatewayError; use crate::gateway::events::Events; use crate::types::{ - self, Channel, ChannelUpdate, Composite, Guild, GuildRoleCreate, GuildRoleUpdate, JsonField, - RoleObject, Snowflake, UpdateMessage, WebSocketEvent, + self, AutoModerationRule, AutoModerationRuleUpdate, Channel, ChannelCreate, ChannelDelete, + ChannelUpdate, Composite, Guild, GuildRoleCreate, GuildRoleUpdate, JsonField, RoleObject, + Snowflake, ThreadUpdate, UpdateMessage, WebSocketEvent, }; use async_trait::async_trait; use std::any::Any; @@ -512,7 +513,13 @@ impl Gateway { $( let mut message: $message_type = message; let store = self.store.lock().await; - if let Some(to_update) = store.get(&message.id()) { + let id = if message.id().is_some() { + message.id().unwrap() + } else { + event.notify(message).await; + return; + }; + if let Some(to_update) = store.get(&id) { let object = to_update.clone(); let inner_object = object.read().unwrap(); if let Some(_) = inner_object.downcast_ref::<$update_type>() { @@ -526,7 +533,7 @@ impl Gateway { message.set_json(json.to_string()); message.update(downcasted.clone()); } else { - warn!("Received {} for {}, but it has been observed to be a different type!", $name, message.id()) + warn!("Received {} for {}, but it has been observed to be a different type!", $name, id) } } )? @@ -568,70 +575,70 @@ impl Gateway { "READY_SUPPLEMENTAL" => session.ready_supplemental, "APPLICATION_COMMAND_PERMISSIONS_UPDATE" => application.command_permissions_update, "AUTO_MODERATION_RULE_CREATE" =>auto_moderation.rule_create, - "AUTO_MODERATION_RULE_UPDATE" =>auto_moderation.rule_update, + "AUTO_MODERATION_RULE_UPDATE" =>auto_moderation.rule_update AutoModerationRuleUpdate: AutoModerationRule, "AUTO_MODERATION_RULE_DELETE" => auto_moderation.rule_delete, "AUTO_MODERATION_ACTION_EXECUTION" => auto_moderation.action_execution, - "CHANNEL_CREATE" => channel.create, + "CHANNEL_CREATE" => channel.create ChannelCreate: Guild, "CHANNEL_UPDATE" => channel.update ChannelUpdate: Channel, "CHANNEL_UNREAD_UPDATE" => channel.unread_update, - "CHANNEL_DELETE" => channel.delete, + "CHANNEL_DELETE" => channel.delete ChannelDelete: Guild, "CHANNEL_PINS_UPDATE" => channel.pins_update, "CALL_CREATE" => call.create, "CALL_UPDATE" => call.update, "CALL_DELETE" => call.delete, - "THREAD_CREATE" => thread.create, - "THREAD_UPDATE" => thread.update, - "THREAD_DELETE" => thread.delete, - "THREAD_LIST_SYNC" => thread.list_sync, - "THREAD_MEMBER_UPDATE" => thread.member_update, - "THREAD_MEMBERS_UPDATE" => thread.members_update, - "GUILD_CREATE" => guild.create, - "GUILD_UPDATE" => guild.update, - "GUILD_DELETE" => guild.delete, + "THREAD_CREATE" => thread.create, // TODO + "THREAD_UPDATE" => thread.update ThreadUpdate: Channel, + "THREAD_DELETE" => thread.delete, // TODO + "THREAD_LIST_SYNC" => thread.list_sync, // TODO + "THREAD_MEMBER_UPDATE" => thread.member_update, // TODO + "THREAD_MEMBERS_UPDATE" => thread.members_update, // TODO + "GUILD_CREATE" => guild.create, // TODO + "GUILD_UPDATE" => guild.update, // TODO + "GUILD_DELETE" => guild.delete, // TODO "GUILD_AUDIT_LOG_ENTRY_CREATE" => guild.audit_log_entry_create, - "GUILD_BAN_ADD" => guild.ban_add, - "GUILD_BAN_REMOVE" => guild.ban_remove, - "GUILD_EMOJIS_UPDATE" => guild.emojis_update, - "GUILD_STICKERS_UPDATE" => guild.stickers_update, + "GUILD_BAN_ADD" => guild.ban_add, // TODO + "GUILD_BAN_REMOVE" => guild.ban_remove, // TODO + "GUILD_EMOJIS_UPDATE" => guild.emojis_update, // TODO + "GUILD_STICKERS_UPDATE" => guild.stickers_update, // TODO "GUILD_INTEGRATIONS_UPDATE" => guild.integrations_update, "GUILD_MEMBER_ADD" => guild.member_add, "GUILD_MEMBER_REMOVE" => guild.member_remove, - "GUILD_MEMBER_UPDATE" => guild.member_update, - "GUILD_MEMBERS_CHUNK" => guild.members_chunk, + "GUILD_MEMBER_UPDATE" => guild.member_update, // TODO + "GUILD_MEMBERS_CHUNK" => guild.members_chunk, // TODO "GUILD_ROLE_CREATE" => guild.role_create GuildRoleCreate: Guild, "GUILD_ROLE_UPDATE" => guild.role_update GuildRoleUpdate: RoleObject, - "GUILD_ROLE_DELETE" => guild.role_delete, - "GUILD_SCHEDULED_EVENT_CREATE" => guild.role_scheduled_event_create, - "GUILD_SCHEDULED_EVENT_UPDATE" => guild.role_scheduled_event_update, - "GUILD_SCHEDULED_EVENT_DELETE" => guild.role_scheduled_event_delete, + "GUILD_ROLE_DELETE" => guild.role_delete, // TODO + "GUILD_SCHEDULED_EVENT_CREATE" => guild.role_scheduled_event_create, // TODO + "GUILD_SCHEDULED_EVENT_UPDATE" => guild.role_scheduled_event_update, // TODO + "GUILD_SCHEDULED_EVENT_DELETE" => guild.role_scheduled_event_delete, // TODO "GUILD_SCHEDULED_EVENT_USER_ADD" => guild.role_scheduled_event_user_add, "GUILD_SCHEDULED_EVENT_USER_REMOVE" => guild.role_scheduled_event_user_remove, - "PASSIVE_UPDATE_V1" => guild.passive_update_v1, - "INTEGRATION_CREATE" => integration.create, - "INTEGRATION_UPDATE" => integration.update, - "INTEGRATION_DELETE" => integration.delete, - "INTERACTION_CREATE" => interaction.create, - "INVITE_CREATE" => invite.create, - "INVITE_DELETE" => invite.delete, + "PASSIVE_UPDATE_V1" => guild.passive_update_v1, // TODO + "INTEGRATION_CREATE" => integration.create, // TODO + "INTEGRATION_UPDATE" => integration.update, // TODO + "INTEGRATION_DELETE" => integration.delete, // TODO + "INTERACTION_CREATE" => interaction.create, // TODO + "INVITE_CREATE" => invite.create, // TODO + "INVITE_DELETE" => invite.delete, // TODO "MESSAGE_CREATE" => message.create, - "MESSAGE_UPDATE" => message.update, + "MESSAGE_UPDATE" => message.update, // TODO "MESSAGE_DELETE" => message.delete, "MESSAGE_DELETE_BULK" => message.delete_bulk, - "MESSAGE_REACTION_ADD" => message.reaction_add, - "MESSAGE_REACTION_REMOVE" => message.reaction_remove, - "MESSAGE_REACTION_REMOVE_ALL" => message.reaction_remove_all, - "MESSAGE_REACTION_REMOVE_EMOJI" => message.reaction_remove_emoji, + "MESSAGE_REACTION_ADD" => message.reaction_add, // TODO + "MESSAGE_REACTION_REMOVE" => message.reaction_remove, // TODO + "MESSAGE_REACTION_REMOVE_ALL" => message.reaction_remove_all, // TODO + "MESSAGE_REACTION_REMOVE_EMOJI" => message.reaction_remove_emoji, // TODO "MESSAGE_ACK" => message.ack, - "PRESENCE_UPDATE" => user.presence_update, + "PRESENCE_UPDATE" => user.presence_update, // TODO "RELATIONSHIP_ADD" => relationship.add, "RELATIONSHIP_REMOVE" => relationship.remove, "STAGE_INSTANCE_CREATE" => stage_instance.create, - "STAGE_INSTANCE_UPDATE" => stage_instance.update, + "STAGE_INSTANCE_UPDATE" => stage_instance.update, // TODO "STAGE_INSTANCE_DELETE" => stage_instance.delete, "TYPING_START" => user.typing_start, - "USER_UPDATE" => user.update, + "USER_UPDATE" => user.update, // TODO "USER_GUILD_SETTINGS_UPDATE" => user.guild_settings_update, - "VOICE_STATE_UPDATE" => voice.state_update, + "VOICE_STATE_UPDATE" => voice.state_update, // TODO "VOICE_SERVER_UPDATE" => voice.server_update, "WEBHOOKS_UPDATE" => webhooks.update ); diff --git a/src/types/entities/auto_moderation.rs b/src/types/entities/auto_moderation.rs index 77f4fa2..eaec2b0 100644 --- a/src/types/entities/auto_moderation.rs +++ b/src/types/entities/auto_moderation.rs @@ -1,11 +1,13 @@ use std::sync::{Arc, RwLock}; +use crate::gateway::Updateable; +use chorus_macros::Updateable; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; use crate::types::utils::Snowflake; -#[derive(Serialize, Deserialize, Debug, Default, Clone)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, Updateable)] /// See pub struct AutoModerationRule { pub id: Snowflake, diff --git a/src/types/entities/channel.rs b/src/types/entities/channel.rs index a64b44c..361ecb5 100644 --- a/src/types/entities/channel.rs +++ b/src/types/entities/channel.rs @@ -16,7 +16,7 @@ use crate::types::{ #[derive(Default, Debug, Serialize, Deserialize, Clone, Updateable, Composite)] #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] -/// Represents a guild of private channel +/// Represents a guild or private channel /// /// # Reference /// See diff --git a/src/types/entities/invite.rs b/src/types/entities/invite.rs index 1e6befc..842db3f 100644 --- a/src/types/entities/invite.rs +++ b/src/types/entities/invite.rs @@ -21,7 +21,7 @@ pub struct Invite { pub flags: Option, pub guild: Option, pub guild_id: Option, - pub guild_scheduled_event: Option, + pub guild_scheduled_event: Option>>, #[serde(rename = "type")] pub invite_type: Option, pub inviter: Option, diff --git a/src/types/entities/message.rs b/src/types/entities/message.rs index f104f97..d7ef01c 100644 --- a/src/types/entities/message.rs +++ b/src/types/entities/message.rs @@ -1,3 +1,5 @@ +use std::sync::{Arc, RwLock}; + use serde::{Deserialize, Serialize}; use crate::types::{ @@ -84,7 +86,7 @@ pub struct MessageInteraction { pub interaction_type: u8, pub name: String, pub user: User, - pub member: Option, + pub member: Option>>, } #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] diff --git a/src/types/events/auto_moderation.rs b/src/types/events/auto_moderation.rs index 0a1600b..376e523 100644 --- a/src/types/events/auto_moderation.rs +++ b/src/types/events/auto_moderation.rs @@ -1,3 +1,5 @@ +use crate::types::JsonField; +use chorus_macros::JsonField; use serde::{Deserialize, Serialize}; use crate::types::{ @@ -5,6 +7,8 @@ use crate::types::{ WebSocketEvent, }; +use super::UpdateMessage; + #[derive(Debug, Deserialize, Serialize, Default, Clone)] /// See pub struct AutoModerationRuleCreate { @@ -14,11 +18,19 @@ pub struct AutoModerationRuleCreate { impl WebSocketEvent for AutoModerationRuleCreate {} -#[derive(Debug, Deserialize, Serialize, Default, Clone)] +#[derive(Debug, Deserialize, Serialize, Default, Clone, JsonField)] /// See pub struct AutoModerationRuleUpdate { #[serde(flatten)] pub rule: AutoModerationRule, + #[serde(skip)] + pub json: String, +} + +impl UpdateMessage for AutoModerationRuleUpdate { + fn id(&self) -> Option { + Some(self.rule.id) + } } impl WebSocketEvent for AutoModerationRuleUpdate {} diff --git a/src/types/events/channel.rs b/src/types/events/channel.rs index 017c50e..ae84b79 100644 --- a/src/types/events/channel.rs +++ b/src/types/events/channel.rs @@ -1,6 +1,7 @@ use std::sync::{Arc, RwLock}; use crate::types::events::WebSocketEvent; +use crate::types::Guild; use crate::types::{entities::Channel, JsonField, Snowflake}; use chorus_macros::JsonField; use chrono::{DateTime, Utc}; @@ -18,15 +19,33 @@ pub struct ChannelPinsUpdate { impl WebSocketEvent for ChannelPinsUpdate {} -#[derive(Debug, Default, Deserialize, Serialize, Clone)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)] /// See pub struct ChannelCreate { #[serde(flatten)] pub channel: Channel, + #[serde(skip)] + pub json: String, } impl WebSocketEvent for ChannelCreate {} +impl UpdateMessage for ChannelCreate { + fn id(&self) -> Option { + self.channel.guild_id + } + + fn update(&mut self, object_to_update: Arc>) { + let mut write = object_to_update.write().unwrap(); + let update = Arc::new(RwLock::new(self.channel.clone())); + if write.channels.is_some() { + write.channels.as_mut().unwrap().push(update); + } else { + write.channels = Some(Vec::from([update])); + } + } +} + #[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)] /// See pub struct ChannelUpdate { @@ -43,8 +62,8 @@ impl UpdateMessage for ChannelUpdate { let mut write = object_to_update.write().unwrap(); *write = self.channel.clone(); } - fn id(&self) -> Snowflake { - self.channel.id + fn id(&self) -> Option { + Some(self.channel.id) } } @@ -68,11 +87,39 @@ pub struct ChannelUnreadUpdateObject { impl WebSocketEvent for ChannelUnreadUpdate {} -#[derive(Debug, Default, Deserialize, Serialize, Clone)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)] /// See pub struct ChannelDelete { #[serde(flatten)] pub channel: Channel, + #[serde(skip)] + pub json: String, +} + +impl UpdateMessage for ChannelDelete { + fn id(&self) -> Option { + self.channel.guild_id + } + + fn update(&mut self, object_to_update: Arc>) { + if self.id().is_none() { + return; + } + let mut write = object_to_update.write().unwrap(); + if write.channels.is_none() { + return; + } + for (iteration, item) in (0_u32..).zip(write.channels.as_mut().unwrap().iter()) { + if item.read().unwrap().id == self.id().unwrap() { + write + .channels + .as_mut() + .unwrap() + .swap_remove(iteration as usize); + return; + } + } + } } impl WebSocketEvent for ChannelDelete {} diff --git a/src/types/events/guild.rs b/src/types/events/guild.rs index 5fac86b..0afa9d6 100644 --- a/src/types/events/guild.rs +++ b/src/types/events/guild.rs @@ -180,8 +180,8 @@ pub struct GuildRoleCreate { impl WebSocketEvent for GuildRoleCreate {} impl UpdateMessage for GuildRoleCreate { - fn id(&self) -> Snowflake { - self.guild_id + fn id(&self) -> Option { + Some(self.guild_id) } fn update(&mut self, object_to_update: Arc>) { @@ -210,15 +210,13 @@ pub struct GuildRoleUpdate { impl WebSocketEvent for GuildRoleUpdate {} impl UpdateMessage for GuildRoleUpdate { - fn id(&self) -> Snowflake { - self.role.id + fn id(&self) -> Option { + Some(self.role.id) } fn update(&mut self, object_to_update: Arc>) { - println!("Processing Role Update. Name: {}", self.role.name); let mut write = object_to_update.write().unwrap(); *write = self.role.clone(); - println!("Updated role: Name: {}", write.name); } } diff --git a/src/types/events/mod.rs b/src/types/events/mod.rs index 0a296fb..4f287ce 100644 --- a/src/types/events/mod.rs +++ b/src/types/events/mod.rs @@ -122,7 +122,7 @@ where fn update(&mut self, object_to_update: Arc>) { update_object(self.get_json(), object_to_update) } - fn id(&self) -> Snowflake; + fn id(&self) -> Option; } pub(crate) trait JsonField: Clone { diff --git a/src/types/events/thread.rs b/src/types/events/thread.rs index 2faecf7..19f1cde 100644 --- a/src/types/events/thread.rs +++ b/src/types/events/thread.rs @@ -1,8 +1,11 @@ +use chorus_macros::JsonField; use serde::{Deserialize, Serialize}; use crate::types::entities::{Channel, ThreadMember}; use crate::types::events::WebSocketEvent; -use crate::types::Snowflake; +use crate::types::{JsonField, Snowflake}; + +use super::UpdateMessage; #[derive(Debug, Default, Deserialize, Serialize, Clone)] /// See @@ -13,15 +16,23 @@ pub struct ThreadCreate { impl WebSocketEvent for ThreadCreate {} -#[derive(Debug, Default, Deserialize, Serialize, Clone)] +#[derive(Debug, Default, Deserialize, Serialize, Clone, JsonField)] /// See pub struct ThreadUpdate { #[serde(flatten)] pub thread: Channel, + #[serde(skip)] + pub json: String, } impl WebSocketEvent for ThreadUpdate {} +impl UpdateMessage for ThreadUpdate { + fn id(&self) -> Option { + Some(self.thread.id) + } +} + #[derive(Debug, Default, Deserialize, Serialize, Clone)] /// See pub struct ThreadDelete {