Cleanup and refactoring wallets

+ clippy + fmt
This commit is contained in:
Joey Hines 2022-12-20 19:30:56 -07:00
parent 137f01a9b2
commit d8489d336f
Signed by: joeyahines
GPG Key ID: 995E531F7A569DDB
7 changed files with 127 additions and 71 deletions

View File

@ -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<String>,
}
#[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<RandomConfig>,
#[serde(default)]
pub wallets: Vec<Wallet>,
pub wallet_manager: WalletManager,
}
impl BotConfig {

View File

@ -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::<GlobalData>().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",
)
.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?;

View File

@ -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::<UserId>().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,31 +60,24 @@ async fn gift(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
args.advance();
let amount = args.parse::<i64>()?;
let amount = args.parse::<u32>()?;
let mut data = ctx.data.write().await;
let global_data = data.get_mut::<GlobalData>().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;
}
} else {
let target_user = msg
.guild(&ctx.cache)
.unwrap()
@ -112,8 +92,8 @@ async fn gift(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
),
)
.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::<GlobalData>().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;
}

View File

@ -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::<GlobalData>().unwrap();
global_data
.cfg
.save(&global_data.args.cfg_path)
.await
.expect("Error saving config");
}
Err(why) => {
println!("Command '{}' returned error {:?}", command_name, why);

View File

@ -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),
}
}
}

View File

@ -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;

68
src/wallet/mod.rs Normal file
View File

@ -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<Wallet>,
}
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(())
}
}