From d8489d336f655b8c65d33b9b64780791a54090fe Mon Sep 17 00:00:00 2001 From: Joey Hines Date: Tue, 20 Dec 2022 19:30:56 -0700 Subject: [PATCH] Cleanup and refactoring wallets + clippy + fmt --- src/config.rs | 10 ++---- src/discord/album.rs | 39 +++++++++++----------- src/discord/fren_coin.rs | 70 ++++++++++++++-------------------------- src/discord/mod.rs | 8 +++++ src/error.rs | 2 ++ src/main.rs | 1 + src/wallet/mod.rs | 68 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 127 insertions(+), 71 deletions(-) create mode 100644 src/wallet/mod.rs diff --git a/src/config.rs b/src/config.rs index 3043615..655c8a3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -2,6 +2,7 @@ use crate::error::Error; use crate::error::Error::NoAlbumFound; use crate::imgur; use crate::imgur::Image; +use crate::wallet::WalletManager; use config::{Config, File}; use rand::prelude::SliceRandom; use serde::{Deserialize, Serialize}; @@ -31,12 +32,6 @@ pub struct RandomConfig { pub responses: Vec, } -#[derive(Debug, Deserialize, Serialize, Clone)] -pub struct Wallet { - pub owner: UserId, - pub coin_count: i64, -} - #[derive(Debug, Deserialize, Serialize, Clone)] pub struct BotConfig { pub bot_token: String, @@ -49,8 +44,7 @@ pub struct BotConfig { #[serde(default)] pub randoms: Vec, - #[serde(default)] - pub wallets: Vec, + pub wallet_manager: WalletManager, } impl BotConfig { diff --git a/src/discord/album.rs b/src/discord/album.rs index 12f8913..f0d49c8 100644 --- a/src/discord/album.rs +++ b/src/discord/album.rs @@ -1,5 +1,6 @@ use crate::config::AlbumConfig; use crate::error::Error; +use crate::imgur::get_album_images; use crate::{command, group, GlobalData}; use serenity::client::Context; use serenity::framework::standard::{Args, CommandResult}; @@ -38,29 +39,33 @@ async fn add_album(ctx: &Context, msg: &Message, mut args: Args) -> CommandResul let global_data = data.get_mut::().unwrap(); - let old_config = global_data.cfg.clone(); + let images = match get_album_images(&global_data.cfg.imgur_client_id, &album_id).await { + Ok(img) => img, + Err(e) => { + msg.reply( + &ctx.http, + "Error adding album, check your link and try again", + ) + .await?; + + println!("Error adding album: {}", e); + + return Ok(()); + } + }; global_data.cfg.albums.push(AlbumConfig { album_id, name: album_name.clone(), }); - global_data.cfg.save(&global_data.args.cfg_path).await?; + global_data + .bot_state + .albums + .insert(album_name.clone(), images); - if global_data.reload().await.is_err() { - global_data.cfg = old_config; - - global_data.cfg.save(&global_data.args.cfg_path).await?; - - msg.reply( - &ctx.http, - "Error adding album, check your link and try again", - ) + msg.reply(&ctx.http, format!("{} album added!", album_name)) .await?; - } else { - msg.reply(&ctx.http, format!("{} album added!", album_name)) - .await?; - } Ok(()) } @@ -82,9 +87,7 @@ async fn remove_album(ctx: &Context, msg: &Message, args: Args) -> CommandResult .albums .retain(|album| !album.name.eq_ignore_ascii_case(&album_name)); - global_data.cfg.save(&global_data.args.cfg_path).await?; - - global_data.reload().await?; + global_data.bot_state.albums.remove(&album_name); msg.reply(&ctx.http, format!("{} album removed!", album_name)) .await?; diff --git a/src/discord/fren_coin.rs b/src/discord/fren_coin.rs index 346bd77..5cf50c2 100644 --- a/src/discord/fren_coin.rs +++ b/src/discord/fren_coin.rs @@ -1,5 +1,6 @@ -use crate::config::{BotConfig, GlobalData, Wallet}; +use crate::config::GlobalData; use crate::error::Error; +use crate::wallet::WalletError; use crate::{command, group}; use rand::{thread_rng, Rng}; use serenity::client::Context; @@ -12,18 +13,6 @@ use serenity::prelude::Mentionable; #[commands(balance, gift)] pub struct FrenCoin; -pub fn get_user_wallet(cfg: &mut BotConfig, discord_id: UserId) -> &mut Wallet { - if let Some(user_ndx) = cfg.wallets.iter().position(|u| u.owner == discord_id) { - &mut cfg.wallets[user_ndx] - } else { - cfg.wallets.push(Wallet { - owner: discord_id, - coin_count: 100, - }); - cfg.wallets.last_mut().unwrap() - } -} - #[command] #[description("Get your current balance")] #[aliases("audit")] @@ -34,7 +23,7 @@ async fn balance(ctx: &Context, msg: &Message, args: Args) -> CommandResult { let user = args.parse::().unwrap_or(msg.author.id); - let wallet = get_user_wallet(&mut global_data.cfg, user); + let wallet = global_data.cfg.wallet_manager.get_user_wallet(user); msg.reply( &ctx.http, @@ -51,8 +40,6 @@ async fn balance(ctx: &Context, msg: &Message, args: Args) -> CommandResult { ) .await?; - global_data.cfg.save(&global_data.args.cfg_path).await?; - Ok(()) } @@ -73,47 +60,40 @@ async fn gift(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { args.advance(); - let amount = args.parse::()?; + let amount = args.parse::()?; let mut data = ctx.data.write().await; let global_data = data.get_mut::().unwrap(); + if let Err(e) = global_data + .cfg + .wallet_manager + .transfer_funds(msg.author.id, target, amount) { - let author_wallet = get_user_wallet(&mut global_data.cfg, msg.author.id); - if author_wallet.coin_count < amount { + if let WalletError::NotEnoughFunds = e { msg.reply( &ctx.http, "Sorry pal, I can't give credit. Come back when you're a bit mmmm richer.", ) .await?; - return Ok(()); } - - author_wallet.coin_count -= amount; - } - - { - let target_wallet = get_user_wallet(&mut global_data.cfg, target); - - target_wallet.coin_count += amount; - } - - let target_user = msg - .guild(&ctx.cache) - .unwrap() - .member(&ctx.http, target) + } else { + let target_user = msg + .guild(&ctx.cache) + .unwrap() + .member(&ctx.http, target) + .await?; + msg.reply( + &ctx.http, + format!( + "You have gifted {} {} fren coins!", + target_user.mention(), + amount + ), + ) .await?; - msg.reply( - &ctx.http, - format!( - "You have gifted {} {} fren coins!", - target_user.mention(), - amount - ), - ) - .await?; + } - global_data.cfg.save(&global_data.args.cfg_path).await?; Ok(()) } @@ -134,7 +114,7 @@ pub async fn give_coin( let global_data = data.get_mut::().unwrap(); { - let wallet = get_user_wallet(&mut global_data.cfg, user); + let wallet = global_data.cfg.wallet_manager.get_user_wallet(user); wallet.coin_count += numer_of_coins; } diff --git a/src/discord/mod.rs b/src/discord/mod.rs index 26c67e0..615cbbb 100644 --- a/src/discord/mod.rs +++ b/src/discord/mod.rs @@ -123,6 +123,14 @@ pub async fn after( Ok(()) => { println!("Processed command '{}'", command_name); give_coin(ctx, msg.author.id, 0.10, 10).await.unwrap(); + + let mut data = ctx.data.write().await; + let global_data = data.get_mut::().unwrap(); + global_data + .cfg + .save(&global_data.args.cfg_path) + .await + .expect("Error saving config"); } Err(why) => { println!("Command '{}' returned error {:?}", command_name, why); diff --git a/src/error.rs b/src/error.rs index bdabc2e..0d4fd20 100644 --- a/src/error.rs +++ b/src/error.rs @@ -11,6 +11,7 @@ pub enum Error { SerenityError(serenity::Error), TeraError(tera::Error), NoAlbumFound, + FrenCoin(crate::wallet::WalletError), } impl StdError for Error {} @@ -41,6 +42,7 @@ impl Display for Error { Error::SerenityError(e) => write!(f, "Discord error: {}", e), Error::TeraError(e) => write!(f, "Tera error: {}", e), Error::NoAlbumFound => write!(f, "No album found"), + Error::FrenCoin(e) => write!(f, "Fren coin error: {}", e), } } } diff --git a/src/main.rs b/src/main.rs index 7bc63e2..1f5a011 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ mod config; mod discord; mod error; mod imgur; +mod wallet; use crate::config::{create_story_channel, Args, BotConfig, GlobalData, StoryRecv, StorySend}; use crate::discord::unrecognised_command_hook; diff --git a/src/wallet/mod.rs b/src/wallet/mod.rs new file mode 100644 index 0000000..4ddef1f --- /dev/null +++ b/src/wallet/mod.rs @@ -0,0 +1,68 @@ +use serde::{Deserialize, Serialize}; +use serenity::model::id::UserId; +use std::fmt::{Display, Formatter}; + +#[derive(Debug, Clone)] +#[allow(dead_code)] +pub enum WalletError { + NotEnoughFunds, + InvalidTarget, +} + +impl Display for WalletError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + WalletError::NotEnoughFunds => write!(f, "Not enough funds"), + WalletError::InvalidTarget => write!(f, "Invalid target"), + } + } +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct Wallet { + pub owner: UserId, + pub coin_count: i64, +} + +#[derive(Debug, Deserialize, Serialize, Clone, Default)] +pub struct WalletManager { + #[serde(default)] + wallets: Vec, +} + +impl WalletManager { + pub fn get_user_wallet(&mut self, discord_id: UserId) -> &mut Wallet { + if let Some(user_ndx) = self.wallets.iter().position(|u| u.owner == discord_id) { + &mut self.wallets[user_ndx] + } else { + self.wallets.push(Wallet { + owner: discord_id, + coin_count: 100, + }); + self.wallets.last_mut().unwrap() + } + } + + pub fn transfer_funds( + &mut self, + src: UserId, + dest: UserId, + amount: u32, + ) -> Result<(), WalletError> { + { + let src_wallet = self.get_user_wallet(src); + if src_wallet.coin_count < amount as i64 { + return Err(WalletError::NotEnoughFunds); + } + src_wallet.coin_count -= amount as i64; + } + + { + let dest_wallet = self.get_user_wallet(dest); + + dest_wallet.coin_count += amount as i64; + } + + Ok(()) + } +}