From 37d5f4c8037b3b8063a9e3d3de57963ffacfbc21 Mon Sep 17 00:00:00 2001 From: CircuitSacul Date: Tue, 2 Aug 2022 02:43:48 -0400 Subject: [PATCH 1/4] skip handling reactions for non-vote emojis --- sqlx-data.json | 20 +++++++++++++++ src/cache/cache.rs | 3 ++- src/core/starboard/reaction_events.rs | 9 +++++-- src/database/models/guild.rs | 35 +++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 3 deletions(-) diff --git a/sqlx-data.json b/sqlx-data.json index fafda330..2e87c07d 100644 --- a/sqlx-data.json +++ b/sqlx-data.json @@ -748,6 +748,26 @@ }, "query": "INSERT INTO users\n (user_id, is_bot)\n VALUES ($1, $2)\n RETURNING *" }, + "3b91600c3d4a4dde62ffdfc767aea020f62c286b4072bf89f32f2a346646b265": { + "describe": { + "columns": [ + { + "name": "array", + "ordinal": 0, + "type_info": "TextArray" + } + ], + "nullable": [ + null + ], + "parameters": { + "Left": [ + "Int8" + ] + } + }, + "query": "SELECT ARRAY (\n SELECT unnest(upvote_emojis || downvote_emojis)\n FROM starboards\n WHERE guild_id=$1\n )" + }, "3d80c09db40235cdb95e62e6aec95fcb75aae0b927b8e0d171bacd4954fb5f7b": { "describe": { "columns": [ diff --git a/src/cache/cache.rs b/src/cache/cache.rs index 6be56779..cc474a6f 100644 --- a/src/cache/cache.rs +++ b/src/cache/cache.rs @@ -32,6 +32,7 @@ pub struct Cache { // database side pub autostar_channel_ids: AsyncDashSet>, + pub guild_vote_emojis: AsyncDashMap>, // autocomplete pub guild_autostar_channel_names: stretto::AsyncCache, Vec>, @@ -50,6 +51,7 @@ impl Cache { ) .unwrap(), autostar_channel_ids: autostar_channel_ids.into(), + guild_vote_emojis: DashMap::new().into(), guild_autostar_channel_names: stretto::AsyncCache::new( (constants::MAX_NAMES * 10).try_into().unwrap(), constants::MAX_NAMES.into(), @@ -95,7 +97,6 @@ impl Cache { }) } - // "fetch or get" methods pub async fn fog_message( &self, bot: &StarboardBot, diff --git a/src/core/starboard/reaction_events.rs b/src/core/starboard/reaction_events.rs index 742334ed..9b5b4447 100644 --- a/src/core/starboard/reaction_events.rs +++ b/src/core/starboard/reaction_events.rs @@ -5,7 +5,7 @@ use twilight_model::gateway::payload::incoming::{ use crate::{ client::bot::StarboardBot, core::emoji::SimpleEmoji, - database::{Member, Message, User, Vote}, + database::{Guild, Member, Message, User, Vote}, map_dup_none, unwrap_id, }; @@ -30,6 +30,12 @@ pub async fn handle_reaction_add( return Ok(()); } + let emoji = SimpleEmoji::from(event.emoji.clone()); + + if !Guild::is_vote_emoji(bot, unwrap_id!(guild_id), &emoji.raw).await? { + return Ok(()); + } + let orig_msg = Message::get_original(&bot.pool, unwrap_id!(event.message_id)).await?; let orig_msg = match orig_msg { None => { @@ -84,7 +90,6 @@ pub async fn handle_reaction_add( Some(msg) => msg, }; - let emoji = SimpleEmoji::from(event.emoji.clone()); let configs = StarboardConfig::list_for_channel(bot, guild_id, event.channel_id).await?; let status = VoteStatus::get_vote_status(bot, &emoji, configs, event.message_id, event.channel_id).await; diff --git a/src/database/models/guild.rs b/src/database/models/guild.rs index e76ff209..d455555b 100644 --- a/src/database/models/guild.rs +++ b/src/database/models/guild.rs @@ -1,5 +1,7 @@ use chrono::{DateTime, Utc}; +use crate::client::bot::StarboardBot; + #[derive(Debug)] pub struct Guild { pub guild_id: i64, @@ -17,4 +19,37 @@ impl Guild { .await .map_err(|e| e.into()) } + + // helper methods + pub async fn is_vote_emoji( + bot: &StarboardBot, + guild_id: i64, + emoji_raw: &String, + ) -> sqlx::Result { + let is_cached_emoji = bot.cache.guild_vote_emojis.with(&guild_id, |_, emojis| { + emojis.as_ref().map(|emojis| emojis.contains(emoji_raw)) + }); + + if let Some(val) = is_cached_emoji { + Ok(val) + } else { + let emojis = sqlx::query!( + "SELECT ARRAY ( + SELECT unnest(upvote_emojis || downvote_emojis) + FROM starboards + WHERE guild_id=$1 + )", + guild_id, + ) + .fetch_one(&bot.pool) + .await? + .array + .unwrap_or_else(|| Vec::new()); + + let is_vote = emojis.contains(emoji_raw); + bot.cache.guild_vote_emojis.insert(guild_id, emojis); + + Ok(is_vote) + } + } } From c4fa05bd263bfe49897ee8f2d4f150cbf3e5ac18 Mon Sep 17 00:00:00 2001 From: CircuitSacul Date: Tue, 2 Aug 2022 11:52:29 -0400 Subject: [PATCH 2/4] fix logic to work for overrides --- sqlx-data.json | 70 ++++++++++++++++------- src/core/starboard/config.rs | 38 +++++++++++- src/core/starboard/reaction_events.rs | 4 +- src/database/models/guild.rs | 35 ------------ src/database/models/starboard_override.rs | 13 +++++ 5 files changed, 102 insertions(+), 58 deletions(-) diff --git a/sqlx-data.json b/sqlx-data.json index 2e87c07d..9364b351 100644 --- a/sqlx-data.json +++ b/sqlx-data.json @@ -748,26 +748,6 @@ }, "query": "INSERT INTO users\n (user_id, is_bot)\n VALUES ($1, $2)\n RETURNING *" }, - "3b91600c3d4a4dde62ffdfc767aea020f62c286b4072bf89f32f2a346646b265": { - "describe": { - "columns": [ - { - "name": "array", - "ordinal": 0, - "type_info": "TextArray" - } - ], - "nullable": [ - null - ], - "parameters": { - "Left": [ - "Int8" - ] - } - }, - "query": "SELECT ARRAY (\n SELECT unnest(upvote_emojis || downvote_emojis)\n FROM starboards\n WHERE guild_id=$1\n )" - }, "3d80c09db40235cdb95e62e6aec95fcb75aae0b927b8e0d171bacd4954fb5f7b": { "describe": { "columns": [ @@ -2354,6 +2334,56 @@ }, "query": "INSERT INTO permrole_starboards\n (permrole_id, starboard_id)\n VALUES ($1, $2)\n RETURNING *" }, + "e0d3435ac460506de5e62af8dea8bf9151a123a5e958a706241e15206499076c": { + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Int4" + }, + { + "name": "guild_id", + "ordinal": 1, + "type_info": "Int8" + }, + { + "name": "name", + "ordinal": 2, + "type_info": "Text" + }, + { + "name": "starboard_id", + "ordinal": 3, + "type_info": "Int4" + }, + { + "name": "channel_ids", + "ordinal": 4, + "type_info": "Int8Array" + }, + { + "name": "overrides", + "ordinal": 5, + "type_info": "Json" + } + ], + "nullable": [ + false, + false, + false, + false, + false, + false + ], + "parameters": { + "Left": [ + "Int4" + ] + } + }, + "query": "SELECT * FROM overrides WHERE starboard_id=$1" + }, "e605d15eeb3e0939bc83e98b98b9ac9814bf2f0983ebdc30c235d8b530bf0ada": { "describe": { "columns": [ diff --git a/src/core/starboard/config.rs b/src/core/starboard/config.rs index 1aad1764..93c61bc8 100644 --- a/src/core/starboard/config.rs +++ b/src/core/starboard/config.rs @@ -9,7 +9,7 @@ use crate::{ helpers::settings::overrides::call_with_override_settings, Starboard, StarboardOverride, StarboardSettings, }, - errors::StarboardError, + errors::{StarboardError, StarboardResult}, unwrap_id, }; @@ -68,4 +68,40 @@ impl StarboardConfig { Ok(configs) } + + pub async fn is_guild_vote_emojis( + bot: &StarboardBot, + guild_id: i64, + emoji_raw: &String, + ) -> StarboardResult { + if let Some(is_vote_emoji) = bot.cache.guild_vote_emojis.with(&guild_id, |_, emojis| { + emojis.as_ref().map(|emojis| emojis.contains(emoji_raw)) + }) { + Ok(is_vote_emoji) + } else { + let mut emojis = Vec::new(); + let starboards = Starboard::list_by_guild(&bot.pool, guild_id).await?; + for sb in starboards { + emojis.extend(sb.settings.upvote_emojis); + emojis.extend(sb.settings.downvote_emojis); + + let configs = StarboardOverride::list_by_starboard(&bot.pool, sb.id).await?; + for c in configs { + let ov = c.get_overrides()?; + if let Some(upvote_emojis) = ov.upvote_emojis { + emojis.extend(upvote_emojis); + } + if let Some(downvote_emojis) = ov.downvote_emojis { + emojis.extend(downvote_emojis); + } + } + } + + let is_vote_emoji = emojis.contains(emoji_raw); + // cache the value + bot.cache.guild_vote_emojis.insert(guild_id, emojis); + + Ok(is_vote_emoji) + } + } } diff --git a/src/core/starboard/reaction_events.rs b/src/core/starboard/reaction_events.rs index 9b5b4447..e3b1b379 100644 --- a/src/core/starboard/reaction_events.rs +++ b/src/core/starboard/reaction_events.rs @@ -5,7 +5,7 @@ use twilight_model::gateway::payload::incoming::{ use crate::{ client::bot::StarboardBot, core::emoji::SimpleEmoji, - database::{Guild, Member, Message, User, Vote}, + database::{Member, Message, User, Vote}, map_dup_none, unwrap_id, }; @@ -32,7 +32,7 @@ pub async fn handle_reaction_add( let emoji = SimpleEmoji::from(event.emoji.clone()); - if !Guild::is_vote_emoji(bot, unwrap_id!(guild_id), &emoji.raw).await? { + if !StarboardConfig::is_guild_vote_emojis(bot, unwrap_id!(guild_id), &emoji.raw).await? { return Ok(()); } diff --git a/src/database/models/guild.rs b/src/database/models/guild.rs index d455555b..e76ff209 100644 --- a/src/database/models/guild.rs +++ b/src/database/models/guild.rs @@ -1,7 +1,5 @@ use chrono::{DateTime, Utc}; -use crate::client::bot::StarboardBot; - #[derive(Debug)] pub struct Guild { pub guild_id: i64, @@ -19,37 +17,4 @@ impl Guild { .await .map_err(|e| e.into()) } - - // helper methods - pub async fn is_vote_emoji( - bot: &StarboardBot, - guild_id: i64, - emoji_raw: &String, - ) -> sqlx::Result { - let is_cached_emoji = bot.cache.guild_vote_emojis.with(&guild_id, |_, emojis| { - emojis.as_ref().map(|emojis| emojis.contains(emoji_raw)) - }); - - if let Some(val) = is_cached_emoji { - Ok(val) - } else { - let emojis = sqlx::query!( - "SELECT ARRAY ( - SELECT unnest(upvote_emojis || downvote_emojis) - FROM starboards - WHERE guild_id=$1 - )", - guild_id, - ) - .fetch_one(&bot.pool) - .await? - .array - .unwrap_or_else(|| Vec::new()); - - let is_vote = emojis.contains(emoji_raw); - bot.cache.guild_vote_emojis.insert(guild_id, emojis); - - Ok(is_vote) - } - } } diff --git a/src/database/models/starboard_override.rs b/src/database/models/starboard_override.rs index 6cf825b6..a0f7de08 100644 --- a/src/database/models/starboard_override.rs +++ b/src/database/models/starboard_override.rs @@ -54,6 +54,19 @@ impl StarboardOverride { .await } + pub async fn list_by_starboard( + pool: &sqlx::PgPool, + starboard_id: i32, + ) -> sqlx::Result> { + sqlx::query_as!( + Self, + "SELECT * FROM overrides WHERE starboard_id=$1", + starboard_id, + ) + .fetch_optional(pool) + .await + } + pub fn get_overrides(&self) -> serde_json::Result { serde_json::from_value(self.overrides.clone()).map_err(|e| e.into()) } From ad94ddb475a298230102b8c216c5e55ef10c90b5 Mon Sep 17 00:00:00 2001 From: CircuitSacul Date: Tue, 2 Aug 2022 12:25:36 -0400 Subject: [PATCH 3/4] fix typo --- src/core/starboard/config.rs | 2 +- src/core/starboard/reaction_events.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/starboard/config.rs b/src/core/starboard/config.rs index 93c61bc8..0d2567df 100644 --- a/src/core/starboard/config.rs +++ b/src/core/starboard/config.rs @@ -69,7 +69,7 @@ impl StarboardConfig { Ok(configs) } - pub async fn is_guild_vote_emojis( + pub async fn is_guild_vote_emoji( bot: &StarboardBot, guild_id: i64, emoji_raw: &String, diff --git a/src/core/starboard/reaction_events.rs b/src/core/starboard/reaction_events.rs index e3b1b379..427a4a9d 100644 --- a/src/core/starboard/reaction_events.rs +++ b/src/core/starboard/reaction_events.rs @@ -32,7 +32,7 @@ pub async fn handle_reaction_add( let emoji = SimpleEmoji::from(event.emoji.clone()); - if !StarboardConfig::is_guild_vote_emojis(bot, unwrap_id!(guild_id), &emoji.raw).await? { + if !StarboardConfig::is_guild_vote_emoji(bot, unwrap_id!(guild_id), &emoji.raw).await? { return Ok(()); } From 1e32e7f71a30724493e99571e4a61a4859f091be Mon Sep 17 00:00:00 2001 From: CircuitSacul Date: Wed, 3 Aug 2022 12:10:17 -0400 Subject: [PATCH 4/4] update cache for relevant commands --- src/interactions/commands/chat/starboard/create.rs | 4 ++++ src/interactions/commands/chat/starboard/delete.rs | 4 ++++ .../commands/chat/starboard/edit/requirements.rs | 12 ++++++++++++ 3 files changed, 20 insertions(+) diff --git a/src/interactions/commands/chat/starboard/create.rs b/src/interactions/commands/chat/starboard/create.rs index 3d676686..be854d74 100644 --- a/src/interactions/commands/chat/starboard/create.rs +++ b/src/interactions/commands/chat/starboard/create.rs @@ -47,6 +47,10 @@ impl CreateStarboard { .await?; } else { ctx.bot.cache.guild_starboard_names.remove(&guild_id).await; + ctx.bot + .cache + .guild_vote_emojis + .remove(&unwrap_id!(guild_id)); ctx.respond_str( &format!("Created starboard '{}' in <#{}>.", name, channel_id), diff --git a/src/interactions/commands/chat/starboard/delete.rs b/src/interactions/commands/chat/starboard/delete.rs index bc0875f0..bfcf6cdf 100644 --- a/src/interactions/commands/chat/starboard/delete.rs +++ b/src/interactions/commands/chat/starboard/delete.rs @@ -25,6 +25,10 @@ impl DeleteStarboard { .guild_autostar_channel_names .remove(&guild_id) .await; + ctx.bot + .cache + .guild_vote_emojis + .remove(&unwrap_id!(guild_id)); ctx.respond_str(&format!("Deleted starboard '{}'.", self.name), false) .await?; } diff --git a/src/interactions/commands/chat/starboard/edit/requirements.rs b/src/interactions/commands/chat/starboard/edit/requirements.rs index 2e64bd8e..3024803c 100644 --- a/src/interactions/commands/chat/starboard/edit/requirements.rs +++ b/src/interactions/commands/chat/starboard/edit/requirements.rs @@ -97,6 +97,12 @@ impl EditRequirements { return Ok(()); } starboard.settings.upvote_emojis = emojis; + + // delete cached value + ctx.bot + .cache + .guild_vote_emojis + .remove(&unwrap_id!(guild_id)); } if let Some(val) = self.downvote_emojis { let emojis = Vec::::from_user_input(val, &ctx.bot, guild_id) @@ -110,6 +116,12 @@ impl EditRequirements { return Ok(()); } starboard.settings.downvote_emojis = emojis; + + // delete cached value + ctx.bot + .cache + .guild_vote_emojis + .remove(&unwrap_id!(guild_id)); } if let Some(val) = self.self_vote { starboard.settings.self_vote = val;