summaryrefslogtreecommitdiff
path: root/src/storage/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/storage/mod.rs')
-rw-r--r--src/storage/mod.rs126
1 files changed, 95 insertions, 31 deletions
diff --git a/src/storage/mod.rs b/src/storage/mod.rs
index 64a3856..2ab54f6 100644
--- a/src/storage/mod.rs
+++ b/src/storage/mod.rs
@@ -1,15 +1,18 @@
-use std::fmt::{Debug, Display};
+use std::fmt::Debug;
use color_eyre::eyre::Result;
use log::*;
-use poise::serenity_prelude::GuildId;
+use poise::serenity_prelude::{GuildId, MessageId};
use redis::{AsyncCommands, Client, FromRedisValue, ToRedisArgs};
-pub mod reactboard;
-pub mod settings;
+mod reactboard;
+mod settings;
+// these are purposefully private. see the comment below
+use reactboard::REACTBOARD_KEY;
+use settings::SETTINGS_KEY;
-pub use reactboard::*;
-pub use settings::*;
+pub use reactboard::ReactBoardEntry;
+pub use settings::{Settings, SettingsProperties};
#[derive(Clone, Debug)]
pub struct Storage {
@@ -23,6 +26,12 @@ impl Storage {
Ok(Self { client })
}
+ /*
+ these are mainly light abstractions to avoid the `let mut con`
+ boilerplate, as well as not require the caller to format the
+ strings for keys
+ */
+
pub async fn get_key<T>(&self, key: &str) -> Result<T>
where
T: FromRedisValue,
@@ -66,6 +75,15 @@ impl Storage {
Ok(())
}
+ pub async fn expire_key(&self, key: &str, expire_seconds: usize) -> Result<()> {
+ debug!("Expiring key {key} in {expire_seconds}");
+
+ let mut con = self.client.get_async_connection().await?;
+ con.expire(key, expire_seconds).await?;
+
+ Ok(())
+ }
+
pub async fn add_to_index<'a>(
&self,
key: &str,
@@ -80,19 +98,60 @@ impl Storage {
Ok(())
}
- pub fn format_settings_key(subkey: impl Display) -> String {
- format!("{}:{subkey}", SETTINGS_KEY)
+ pub async fn get_from_index<T>(&self, key: &str) -> Result<Vec<T>>
+ where
+ T: FromRedisValue,
+ {
+ let index = format!("{key}:index");
+ debug!("Fetching index {index}");
+
+ let mut con = self.client.get_async_connection().await?;
+ let mems = con.smembers(key).await?;
+
+ Ok(mems)
}
- pub async fn create_settings_key(&self, settings: Settings) -> Result<()> {
- let key = Self::format_settings_key(settings.guild_id);
+ // guild settings
+
+ pub async fn create_guild_settings(&self, settings: Settings) -> Result<()> {
+ let key = format!("{SETTINGS_KEY}:{}", settings.guild_id);
self.set_key(&key, &settings).await?;
+ // adding to index since we need to look all of these up sometimes
self.add_to_index(SETTINGS_KEY, settings).await?;
Ok(())
}
+ pub async fn get_guild_settings(&self, guild_id: &GuildId) -> Result<Settings> {
+ debug!("Fetching guild settings for {guild_id}");
+
+ let key = format!("{SETTINGS_KEY}:{guild_id}");
+ let settings: Settings = self.get_key(&key).await?;
+
+ Ok(settings)
+ }
+
+ pub async fn delete_guild_settings(&self, guild_id: &GuildId) -> Result<()> {
+ let key = format!("{SETTINGS_KEY}:{guild_id}");
+ self.delete_key(&key).await?;
+
+ Ok(())
+ }
+
+ pub async fn guild_settings_exist(&self, guild_id: &GuildId) -> Result<bool> {
+ let key = format!("{SETTINGS_KEY}:{guild_id}");
+ self.key_exists(&key).await
+ }
+
+ pub async fn get_all_guild_settings(&self) -> Result<Vec<Settings>> {
+ debug!("Fetching all guild settings");
+
+ let guilds: Vec<Settings> = self.get_from_index(SETTINGS_KEY).await?;
+
+ Ok(guilds)
+ }
+
/// get guilds that have enabled optional commands
pub async fn get_opted_guilds(&self) -> Result<Vec<GuildId>> {
debug!("Fetching opted-in guilds");
@@ -112,35 +171,40 @@ impl Storage {
Ok(opted)
}
- pub async fn get_all_guild_settings(&self) -> Result<Vec<Settings>> {
- debug!("Fetching all guild settings");
+ // reactboard
- let mut con = self.client.get_async_connection().await?;
- let key = Self::format_settings_key("index");
+ pub async fn create_reactboard_entry(
+ &self,
+ guild_id: &GuildId,
+ entry: ReactBoardEntry,
+ ) -> Result<()> {
+ let key = format!("{REACTBOARD_KEY}:{guild_id}:{}", entry.original_message_id);
- let guilds: Vec<Settings> = con.smembers(key).await?;
+ self.set_key(&key, &entry).await?;
+ self.expire_key(&key, 30 * 24 * 60 * 60).await?; // 30 days
- Ok(guilds)
+ Ok(())
}
- pub async fn get_guild_settings(&self, guild_id: &GuildId) -> Result<Settings> {
- debug!("Fetching guild settings for {guild_id}");
-
- let key = Self::format_settings_key(guild_id);
- let settings: Settings = self.get_key(&key).await?;
+ pub async fn get_reactboard_entry(
+ &self,
+ guild_id: &GuildId,
+ message_id: &MessageId,
+ ) -> Result<ReactBoardEntry> {
+ debug!("Fetching reactboard entry in {guild_id}");
- Ok(settings)
- }
+ let key = format!("{REACTBOARD_KEY}:{guild_id}:{message_id}");
+ let entry: ReactBoardEntry = self.get_key(&key).await?;
- pub async fn create_reactboard_info_key(&self, reactboard: ReactBoardInfo) -> Result<()> {
- self.set_key(REACT_BOARD_KEY, reactboard).await?;
- Ok(())
+ Ok(entry)
}
- pub async fn get_reactboard_info(&self) -> Result<ReactBoardInfo> {
- debug!("Fetching reactboard info");
- let reactboard: ReactBoardInfo = self.get_key(REACT_BOARD_KEY).await?;
-
- Ok(reactboard)
+ pub async fn reactboard_entry_exists(
+ &self,
+ guild_id: &GuildId,
+ message_id: &MessageId,
+ ) -> Result<bool> {
+ let key = format!("{REACTBOARD_KEY}:{guild_id}:{message_id}");
+ self.key_exists(&key).await
}
}