From 9f5d68f4b2dc36428f8aa3bf0034d2ea325391a0 Mon Sep 17 00:00:00 2001 From: Joey Hines Date: Fri, 20 Jan 2023 16:00:27 -0700 Subject: [PATCH] Moved motivation config to the database + More refactoring + clippy + fmt --- src/config.rs | 17 ------ src/discord/fren_coin.rs | 6 --- src/discord/mod.rs | 5 -- src/discord/motivate.rs | 110 ++++++++++++++++++++++++--------------- src/discord/shop.rs | 12 ++++- src/models/mod.rs | 1 + src/models/motivation.rs | 110 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 189 insertions(+), 72 deletions(-) create mode 100644 src/models/motivation.rs diff --git a/src/config.rs b/src/config.rs index 6aad993..ae3a18c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -21,13 +21,6 @@ pub struct Args { pub cfg_path: PathBuf, } -#[derive(Debug, Deserialize, Serialize, Clone)] -pub struct MotivationConfig { - pub album: Vec, - pub action: Vec, - pub goal: Vec, -} - #[derive(Debug, Deserialize, Serialize, Clone)] pub struct BotConfig { pub bot_token: String, @@ -37,8 +30,6 @@ pub struct BotConfig { pub nft_path: PathBuf, pub db_path: PathBuf, pub admins: Vec, - - pub motivation: MotivationConfig, } impl BotConfig { @@ -49,14 +40,6 @@ impl BotConfig { cfg.try_deserialize() } - - pub async fn save(&self, config_path: &Path) -> Result<(), tokio::io::Error> { - let output_str = toml::to_string_pretty(&self).unwrap(); - - tokio::fs::write(config_path, output_str).await?; - - Ok(()) - } } #[derive(Debug)] diff --git a/src/discord/fren_coin.rs b/src/discord/fren_coin.rs index f8ba71f..880a7ef 100644 --- a/src/discord/fren_coin.rs +++ b/src/discord/fren_coin.rs @@ -117,12 +117,6 @@ pub async fn give_coin( let global_data = data.get_mut::().unwrap(); User::give_funds(&global_data.db, user, number_of_coins as u32)?; - - global_data - .cfg - .save(&global_data.args.cfg_path) - .await - .unwrap(); } Ok(should_get_coin) diff --git a/src/discord/mod.rs b/src/discord/mod.rs index c4c1551..d43a412 100644 --- a/src/discord/mod.rs +++ b/src/discord/mod.rs @@ -136,11 +136,6 @@ pub async fn after( let data = ctx.data.read().await; let global_data = data.get::().unwrap(); - global_data - .cfg - .save(&global_data.args.cfg_path) - .await - .expect("Error saving config"); global_data.db.db.flush_async().await.unwrap(); } diff --git a/src/discord/motivate.rs b/src/discord/motivate.rs index 7820124..7187221 100644 --- a/src/discord/motivate.rs +++ b/src/discord/motivate.rs @@ -1,59 +1,30 @@ -use crate::imgur::{get_album_images, Image}; +use crate::models::motivation::{Motivation, MotivationConfig}; use crate::{command, group, GlobalData}; use magick_rust::{DrawingWand, MagickWand, PixelWand}; -use rand::prelude::IteratorRandom; -use rand::thread_rng; use serenity::client::Context; use serenity::framework::standard::{Args, CommandError, CommandResult}; use serenity::model::channel::{AttachmentType, Message}; use std::borrow::Cow; #[group] -#[commands(motivation)] +#[commands( + motivation, + motivation_add_album, + motivation_add_action, + motivation_add_goal +)] pub struct Motivate; -pub async fn create_image( - global_data: &GlobalData, - border_color: &str, -) -> Result, CommandError> { - let album = &global_data - .cfg - .motivation - .album - .iter() - .choose(&mut thread_rng()) - .unwrap(); +pub async fn create_motivation_image(motivation: Motivation) -> Result, CommandError> { + let motivation_image_blob = reqwest::get(&motivation.image_url).await?.bytes().await?; - let images = get_album_images(&global_data.cfg.imgur_client_id, album).await?; - let motivation_image_link: &Image = images.iter().choose(&mut thread_rng()).unwrap(); - - let motivation_image_blob = reqwest::get(&motivation_image_link.link) - .await? - .bytes() - .await?; - - let action = global_data - .cfg - .motivation - .action - .iter() - .choose(&mut thread_rng()) - .unwrap(); - let goal = global_data - .cfg - .motivation - .goal - .iter() - .choose(&mut thread_rng()) - .unwrap(); - - let motivation = format!("{} {}", action, goal); + let text = format!("{} {}", motivation.action, motivation.goal); let mut wand = MagickWand::new(); let mut border_wand = PixelWand::new(); wand.read_image_blob(motivation_image_blob)?; - border_wand.set_color(border_color)?; + border_wand.set_color(&motivation.border_color)?; let width = wand.get_image_width(); let border = width / 100; wand.border_image( @@ -82,7 +53,7 @@ pub async fn create_image( text_wand.set_fill_color(&text_color_wand); text_wand.set_font_size(0.07 * (wand.get_image_width() as f64)); text_wand.set_text_alignment(magick_rust::bindings::AlignType_CenterAlign); - wand.annotate_image(&text_wand, text_pos_x, text_pos_y, 0.0, &motivation)?; + wand.annotate_image(&text_wand, text_pos_x, text_pos_y, 0.0, &text)?; Ok(wand.write_image_blob("png")?) } @@ -93,7 +64,14 @@ async fn motivation(ctx: &Context, msg: &Message, _args: Args) -> CommandResult let data = ctx.data.read().await; let global_data = data.get::().unwrap(); - let image = create_image(global_data, "white").await?; + let motivation = MotivationConfig::generate_motivation( + &global_data.db, + &global_data.cfg.imgur_client_id, + "white", + ) + .await?; + + let image = create_motivation_image(motivation).await?; msg.channel_id .send_message(&ctx.http, |m| { @@ -107,3 +85,51 @@ async fn motivation(ctx: &Context, msg: &Message, _args: Args) -> CommandResult Ok(()) } + +#[command] +#[only_in(guilds)] +#[description("Add imgur album to the motivation generator")] +async fn motivation_add_album(ctx: &Context, msg: &Message, args: Args) -> CommandResult { + let data = ctx.data.read().await; + let global_data = data.get::().unwrap(); + + let album = args.parse::()?; + + MotivationConfig::add_album(&global_data.db, &album)?; + + msg.reply(&ctx.http, "Done ;)").await?; + + Ok(()) +} + +#[command] +#[only_in(guilds)] +#[description("Add an action to the motivation generator")] +async fn motivation_add_action(ctx: &Context, msg: &Message, args: Args) -> CommandResult { + let data = ctx.data.read().await; + let global_data = data.get::().unwrap(); + + let action = args.rest(); + + MotivationConfig::add_action(&global_data.db, action)?; + + msg.reply(&ctx.http, "Done ;)").await?; + + Ok(()) +} + +#[command] +#[only_in(guilds)] +#[description("Add goal to the motivation generator")] +async fn motivation_add_goal(ctx: &Context, msg: &Message, args: Args) -> CommandResult { + let data = ctx.data.read().await; + let global_data = data.get::().unwrap(); + + let goal = args.rest(); + + MotivationConfig::add_goal(&global_data.db, goal)?; + + msg.reply(&ctx.http, "Done ;)").await?; + + Ok(()) +} diff --git a/src/discord/shop.rs b/src/discord/shop.rs index f7fcbf5..5866413 100644 --- a/src/discord/shop.rs +++ b/src/discord/shop.rs @@ -1,6 +1,7 @@ -use crate::discord::motivate::create_image; +use crate::discord::motivate::create_motivation_image; use crate::error::Error; use crate::inventory::{InventoryError, ItemData, ItemType, Operation}; +use crate::models::motivation::MotivationConfig; use crate::user::{User, UserError}; use crate::{command, group, GlobalData}; use rand::prelude::SliceRandom; @@ -253,7 +254,14 @@ pub async fn restock_shop(ctx: &Context) -> Result<(), CommandError> { tokio::fs::create_dir(&global_data.cfg.nft_path).await? } - let nft = create_image(global_data, "gold").await.unwrap(); + let nft_motivation = MotivationConfig::generate_motivation( + &global_data.db, + &global_data.cfg.imgur_client_id, + "gold", + ) + .await + .unwrap(); + let nft = create_motivation_image(nft_motivation).await.unwrap(); let mut hasher = DefaultHasher::new(); hasher.write(&nft); let nft_hash = hasher.finish(); diff --git a/src/models/mod.rs b/src/models/mod.rs index 83742d5..a62659c 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,3 +1,4 @@ pub mod album; pub mod insult_compliment; +pub mod motivation; pub mod random; diff --git a/src/models/motivation.rs b/src/models/motivation.rs new file mode 100644 index 0000000..12166de --- /dev/null +++ b/src/models/motivation.rs @@ -0,0 +1,110 @@ +use crate::error::Error; +use crate::imgur::get_album_images; +use j_db::database::Database; +use j_db::model::JdbModel; +use rand::prelude::{IteratorRandom, SliceRandom}; +use rand::thread_rng; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct MotivationConfig { + id: Option, + pub album: Vec, + pub action: Vec, + pub goal: Vec, +} + +impl JdbModel for MotivationConfig { + fn id(&self) -> Option { + self.id + } + + fn set_id(&mut self, id: u64) { + self.id = Some(id) + } + + fn tree() -> String { + "Motivation".to_string() + } + + fn check_unique(&self, _: &Self) -> bool { + false + } +} + +impl MotivationConfig { + pub fn get_motivation_config(db: &Database) -> Result { + Ok(db + .filter(|_, _: &MotivationConfig| true)? + .next() + .unwrap_or(Self { + id: None, + album: vec![], + action: vec![], + goal: vec![], + })) + } + + pub fn add_album(db: &Database, album: &str) -> Result<(), Error> { + let mut motivation = Self::get_motivation_config(db)?; + motivation.album.push(album.to_string()); + + db.insert(motivation)?; + + Ok(()) + } + + pub fn add_action(db: &Database, action: &str) -> Result<(), Error> { + let mut motivation = Self::get_motivation_config(db)?; + motivation.action.push(action.to_string()); + + db.insert(motivation)?; + + Ok(()) + } + + pub fn add_goal(db: &Database, goal: &str) -> Result<(), Error> { + let mut motivation = Self::get_motivation_config(db)?; + motivation.goal.push(goal.to_string()); + + db.insert(motivation)?; + + Ok(()) + } + + pub async fn generate_motivation( + db: &Database, + imgur_client_id: &str, + border_color: &str, + ) -> Result { + let motivation = Self::get_motivation_config(db)?; + + let mut images = Vec::new(); + + for album in motivation.album { + let mut album_images = get_album_images(imgur_client_id, &album).await?; + images.append(&mut album_images); + } + + let image = images.choose(&mut thread_rng()).unwrap(); + + let action = motivation.action.iter().choose(&mut thread_rng()).unwrap(); + + let goal = motivation.goal.iter().choose(&mut thread_rng()).unwrap(); + + Ok(Motivation { + image_url: image.link.clone(), + action: action.to_string(), + goal: goal.to_string(), + border_color: border_color.to_string(), + }) + } +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct Motivation { + pub image_url: String, + pub action: String, + pub goal: String, + pub border_color: String, +}