diff --git a/gateway/src/main.rs b/gateway/src/main.rs index 2d1383aa..b1b44984 100644 --- a/gateway/src/main.rs +++ b/gateway/src/main.rs @@ -104,16 +104,7 @@ async fn init_gateway( | Intents::MESSAGE_CONTENT ) .shard_scheme(scheme) - .event_types( - // EventTypeFlags::all() - EventTypeFlags::READY - | EventTypeFlags::GATEWAY_INVALIDATE_SESSION - | EventTypeFlags::GATEWAY_RECONNECT - | EventTypeFlags::SHARD_PAYLOAD - | EventTypeFlags::SHARD_CONNECTED - | EventTypeFlags::SHARD_DISCONNECTED - | EventTypeFlags::MESSAGE_CREATE - ) + .event_types(EventTypeFlags::all()) .queue(Arc::new(queue)) .build() .await?; diff --git a/myriad_rs/src/cache.rs b/myriad_rs/src/cache.rs index 78bcdb9e..62c851fc 100644 --- a/myriad_rs/src/cache.rs +++ b/myriad_rs/src/cache.rs @@ -1,4 +1,6 @@ use twilight_gateway::Event; +use redis::AsyncCommands; +use prost::Message; include!(concat!(env!("OUT_DIR"), "/myriad.cache.rs")); @@ -6,64 +8,213 @@ pub async fn handle_event<'a>( event: Event, rconn: redis::Client ) -> anyhow::Result<()> { + let mut conn = rconn.get_async_connection().await.unwrap(); + match event { - // todo: save private channels (see SaveDMChannelStub / PrivateChannelService) + // todo: save private channels to sql (see SaveDMChannelStub / PrivateChannelService) // todo: save user profiles for some reason (from message create, etc) // todo(dotnet): remove relying on cache.OwnUserId + // todo(dotnet): correctly calculate permissions in guild threads Event::GuildCreate(guild) => { + // todo: clear any existing guild state // save guild itself + conn.hset("discord:guilds", guild.id.get(), CachedGuild{ + id: guild.id.get(), + name: guild.name.to_string(), + owner_id: guild.owner_id.get(), + premium_tier: guild.premium_tier as i32, + }.encode_to_vec()).await?; // save all roles in guild - // save guild-role map + for role in guild.roles.clone().into_iter() { + conn.hset::<&str, u64, Vec, i32>("discord:roles", role.id.get(), CachedRole{ + id: role.id.get(), + name: role.name, + position: role.position as i32, + permissions: role.permissions.bits(), + mentionable: role.mentionable, + }.encode_to_vec()).await?; + // save guild-role map + conn.hset::(format!("discord:guild_roles:{}", guild.id.get()), role.id.get(), 1).await?; + } // save all channels in guild + for channel in guild.channels.clone().into_iter() { + conn.hset::<&str, u64, Vec, i32>("discord:channels", channel.id.get(), CachedChannel{ + id: channel.id.get(), + r#type: channel.kind as i32, + position: channel.position.unwrap_or(0) as i32, + name: channel.name, + permission_overwrites: channel.permission_overwrites.unwrap().into_iter().map(|v| Overwrite{ + id: v.id.get(), + r#type: v.kind as i32, + allow: v.allow.bits(), + deny: v.deny.bits(), + }).collect(), + guild_id: Some(guild.id.get()), + parent_id: channel.parent_id.map(|v| v.get()), + }.encode_to_vec()).await?; + // save guild-channel map + conn.hset::(format!("discord:guild_channels:{}", guild.id.get()), channel.id.get(), 1).await?; + } + // save all threads in guild (as channels lol) - // save guild-channel map + for thread in guild.threads.clone().into_iter() { + conn.hset::<&str, u64, Vec, i32>("discord:channels", thread.id.get(), CachedChannel{ + id: thread.id.get(), + r#type: thread.kind as i32, + position: thread.position.unwrap_or(0) as i32, + name: thread.name, + guild_id: Some(guild.id.get()), + parent_id: thread.parent_id.map(|v| v.get()), + ..Default::default() + }.encode_to_vec()).await?; + // save guild-channel map + conn.hset::(format!("discord:guild_channels:{}", guild.id.get()), thread.id.get(), 1).await?; + } + // save self guild member + conn.hset("discord:guild_members", guild.id.get(), CachedGuildMember{ + roles: guild.members.get(0).unwrap().roles.clone().into_iter().map(|r| r.get()).collect() + }.encode_to_vec()).await?; // c# code also saves users in guildCreate.Members, but I'm pretty sure that doesn't have anything now because intents } Event::GuildUpdate(guild) => { // save guild itself + conn.hset("discord:guilds", guild.id.get(), CachedGuild{ + id: guild.id.get(), + name: guild.name.to_string(), + owner_id: guild.owner_id.get(), + premium_tier: guild.premium_tier as i32, + }.encode_to_vec()).await?; } Event::GuildDelete(guild) => { // delete guild + conn.hdel("discord:guilds", guild.id.get()).await?; + if let Ok(roles) = conn.hkeys::>(format!("discord:guild_roles:{}", guild.id.get())).await { + for role in roles.into_iter() { + conn.hdel("discord:roles", role).await?; + } + } + conn.del(format!("discord:guild_roles:{}", guild.id.get())).await?; + // this probably should also delete all channels/roles/etc of the guild + if let Ok(channel) = conn.hkeys::>(format!("discord:guild_channels:{}", guild.id.get())).await { + conn.hdel("discord:channels", channel).await?; + } + conn.del(format!("discord:guild_channels:{}", guild.id.get())).await?; } Event::MemberUpdate(member) => { // save self guild member + conn.hset("discord:guild_members", member.guild_id.get(), CachedGuildMember{ + roles: member.roles.clone().into_iter().map(|r| r.get()).collect() + }.encode_to_vec()).await?; } Event::ChannelCreate(channel) => { // save channel - // update guild-channel map + conn.hset::<&str, u64, Vec, i32>("discord:channels", channel.id.get(), CachedChannel{ + id: channel.id.get(), + r#type: channel.kind as i32, + position: channel.position.unwrap_or(0) as i32, + name: channel.name.as_deref().map(|v| v.to_string()), + permission_overwrites: channel.permission_overwrites.as_ref().unwrap().into_iter().map(|v| Overwrite{ + id: v.id.get(), + r#type: v.kind as i32, + allow: v.allow.bits(), + deny: v.deny.bits(), + }).collect(), + guild_id: channel.guild_id.map(|v| v.get()), + parent_id: channel.parent_id.map(|v| v.get()), + }.encode_to_vec()).await?; + + // update guild-channel map (if this is a guild channel) + if let Some(guild_id) = channel.guild_id { + conn.hset::(format!("discord:guild_channels:{}", guild_id.get()), channel.id.get(), 1).await?; + } } Event::ChannelUpdate(channel) => { - // save channel + conn.hset::<&str, u64, Vec, i32>("discord:channels", channel.id.get(), CachedChannel{ + id: channel.id.get(), + r#type: channel.kind as i32, + position: channel.position.unwrap_or(0) as i32, + name: channel.name.as_deref().map(|v| v.to_string()), + permission_overwrites: channel.permission_overwrites.as_ref().unwrap().into_iter().map(|v| Overwrite{ + id: v.id.get(), + r#type: v.kind as i32, + allow: v.allow.bits(), + deny: v.deny.bits(), + }).collect(), + guild_id: channel.guild_id.map(|v| v.get()), + parent_id: channel.parent_id.map(|v| v.get()), + }.encode_to_vec()).await?; } Event::ChannelDelete(channel) => { // delete channel + conn.hdel("discord:channels", channel.id.get()).await?; // update guild-channel map + if let Some(guild_id) = channel.guild_id { + conn.hdel(format!("discord:guild_channels:{}", guild_id.get()), channel.id.get()).await?; + } } Event::RoleCreate(role) => { // save role + conn.hset::<&str, u64, Vec, i32>("discord:roles", role.role.id.get(), CachedRole{ + id: role.role.id.get(), + name: role.role.name, + position: role.role.position as i32, + permissions: role.role.permissions.bits(), + mentionable: role.role.mentionable, + }.encode_to_vec()).await?; // update guild-role map + conn.hset::(format!("discord:guild_roles:{}", role.guild_id.get()), role.role.id.get(), 1).await?; } Event::RoleUpdate(role) => { // save role + conn.hset::<&str, u64, Vec, i32>("discord:roles", role.role.id.get(), CachedRole{ + id: role.role.id.get(), + name: role.role.name, + position: role.role.position as i32, + permissions: role.role.permissions.bits(), + mentionable: role.role.mentionable, + }.encode_to_vec()).await?; } Event::RoleDelete(role) => { // delete role + conn.hdel("discord:roles", role.role_id.get()).await?; // update guild-role map + conn.hdel(format!("discord:guild_roles:{}", role.guild_id.get()), role.role_id.get()).await?; } Event::ThreadCreate(thread) => { - // save channel + conn.hset::<&str, u64, Vec, i32>("discord:channels", thread.id.get(), CachedChannel{ + id: thread.id.get(), + r#type: thread.kind as i32, + position: thread.position.unwrap_or(0) as i32, + name: thread.name.as_deref().map(|v| v.to_string()), + guild_id: Some(thread.guild_id.unwrap().get()), + parent_id: thread.parent_id.map(|v| v.get()), + ..Default::default() + }.encode_to_vec()).await?; + + // save guild-channel map + conn.hset::(format!("discord:guild_channels:{}", thread.guild_id.unwrap().get()), thread.id.get(), 1).await?; // update guild-channel map } Event::ThreadUpdate(thread) => { - // save thread + conn.hset::<&str, u64, Vec, i32>("discord:channels", thread.id.get(), CachedChannel{ + id: thread.id.get(), + r#type: thread.kind as i32, + position: thread.position.unwrap_or(0) as i32, + name: thread.name.as_deref().map(|v| v.to_string()), + guild_id: Some(thread.guild_id.unwrap().get()), + parent_id: thread.parent_id.map(|v| v.get()), + ..Default::default() + }.encode_to_vec()).await?; } Event::ThreadDelete(thread) => { // delete channel + conn.hdel("discord:channels", thread.id.get()).await?; // update guild-channel map + conn.hdel(format!("discord:guild_channels:{}", thread.guild_id.get()), thread.id.get()).await?; } Event::ThreadListSync(tls) => { // save channels