Enhancement/updatemessage (#190)

Implements UpdateMessage for some more Gateway Events.
This commit is contained in:
Flori 2023-08-20 16:10:28 +02:00 committed by GitHub
commit 19159b0196
10 changed files with 139 additions and 60 deletions

View File

@ -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
);

View File

@ -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 <https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object>
pub struct AutoModerationRule {
pub id: Snowflake,

View File

@ -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 <https://discord-userdoccers.vercel.app/resources/channel#channels-resource>

View File

@ -21,7 +21,7 @@ pub struct Invite {
pub flags: Option<i32>,
pub guild: Option<InviteGuild>,
pub guild_id: Option<Snowflake>,
pub guild_scheduled_event: Option<GuildScheduledEvent>,
pub guild_scheduled_event: Option<Arc<RwLock<GuildScheduledEvent>>>,
#[serde(rename = "type")]
pub invite_type: Option<i32>,
pub inviter: Option<User>,

View File

@ -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<GuildMember>,
pub member: Option<Arc<RwLock<GuildMember>>>,
}
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]

View File

@ -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 <https://discord.com/developers/docs/topics/gateway-events#auto-moderation-rule-create>
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 <https://discord.com/developers/docs/topics/gateway-events#auto-moderation-rule-update>
pub struct AutoModerationRuleUpdate {
#[serde(flatten)]
pub rule: AutoModerationRule,
#[serde(skip)]
pub json: String,
}
impl UpdateMessage<AutoModerationRule> for AutoModerationRuleUpdate {
fn id(&self) -> Option<Snowflake> {
Some(self.rule.id)
}
}
impl WebSocketEvent for AutoModerationRuleUpdate {}

View File

@ -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 <https://discord.com/developers/docs/topics/gateway-events#channel-create>
pub struct ChannelCreate {
#[serde(flatten)]
pub channel: Channel,
#[serde(skip)]
pub json: String,
}
impl WebSocketEvent for ChannelCreate {}
impl UpdateMessage<Guild> for ChannelCreate {
fn id(&self) -> Option<Snowflake> {
self.channel.guild_id
}
fn update(&mut self, object_to_update: Arc<RwLock<Guild>>) {
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 <https://discord.com/developers/docs/topics/gateway-events#channel-update>
pub struct ChannelUpdate {
@ -43,8 +62,8 @@ impl UpdateMessage<Channel> 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<Snowflake> {
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 <https://discord.com/developers/docs/topics/gateway-events#channel-delete>
pub struct ChannelDelete {
#[serde(flatten)]
pub channel: Channel,
#[serde(skip)]
pub json: String,
}
impl UpdateMessage<Guild> for ChannelDelete {
fn id(&self) -> Option<Snowflake> {
self.channel.guild_id
}
fn update(&mut self, object_to_update: Arc<RwLock<Guild>>) {
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 {}

View File

@ -180,8 +180,8 @@ pub struct GuildRoleCreate {
impl WebSocketEvent for GuildRoleCreate {}
impl UpdateMessage<Guild> for GuildRoleCreate {
fn id(&self) -> Snowflake {
self.guild_id
fn id(&self) -> Option<Snowflake> {
Some(self.guild_id)
}
fn update(&mut self, object_to_update: Arc<RwLock<Guild>>) {
@ -210,15 +210,13 @@ pub struct GuildRoleUpdate {
impl WebSocketEvent for GuildRoleUpdate {}
impl UpdateMessage<RoleObject> for GuildRoleUpdate {
fn id(&self) -> Snowflake {
self.role.id
fn id(&self) -> Option<Snowflake> {
Some(self.role.id)
}
fn update(&mut self, object_to_update: Arc<RwLock<RoleObject>>) {
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);
}
}

View File

@ -122,7 +122,7 @@ where
fn update(&mut self, object_to_update: Arc<RwLock<T>>) {
update_object(self.get_json(), object_to_update)
}
fn id(&self) -> Snowflake;
fn id(&self) -> Option<Snowflake>;
}
pub(crate) trait JsonField: Clone {

View File

@ -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 <https://discord.com/developers/docs/topics/gateway-events#thread-create>
@ -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 <https://discord.com/developers/docs/topics/gateway-events#thread-update>
pub struct ThreadUpdate {
#[serde(flatten)]
pub thread: Channel,
#[serde(skip)]
pub json: String,
}
impl WebSocketEvent for ThreadUpdate {}
impl UpdateMessage<Channel> for ThreadUpdate {
fn id(&self) -> Option<Snowflake> {
Some(self.thread.id)
}
}
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
/// See <https://discord.com/developers/docs/topics/gateway-events#thread-delete>
pub struct ThreadDelete {