diff --git a/src/config.rs b/src/config.rs index 66a9775..a1bb074 100644 --- a/src/config.rs +++ b/src/config.rs @@ -30,6 +30,12 @@ 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, @@ -41,6 +47,9 @@ pub struct BotConfig { #[serde(default)] pub randoms: Vec, + + #[serde(default)] + pub wallets: Vec, } impl BotConfig { diff --git a/src/discord/fren_coin.rs b/src/discord/fren_coin.rs new file mode 100644 index 0000000..715f647 --- /dev/null +++ b/src/discord/fren_coin.rs @@ -0,0 +1,104 @@ +use crate::config::{BotConfig, GlobalData, Wallet}; +use crate::{command, group}; +use serenity::client::Context; +use serenity::framework::standard::{Args, CommandResult}; +use serenity::model::channel::Message; +use serenity::model::id::UserId; +use serenity::prelude::Mentionable; + +#[group] +#[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")] +#[only_in(guilds)] +async fn balance(ctx: &Context, msg: &Message, _args: Args) -> CommandResult { + let mut data = ctx.data.write().await; + let global_data = data.get_mut::().unwrap(); + + let wallet = get_user_wallet(&mut global_data.cfg, msg.author.id); + + msg.reply( + &ctx.http, + format!("Your current balance is {} fren coins!", wallet.coin_count), + ) + .await?; + + global_data.cfg.save(&global_data.args.cfg_path).await?; + + Ok(()) +} + +#[command] +#[only_in(guilds)] +#[description("Gift your frens coins!")] +#[usage("@fren 25")] +async fn gift(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { + let target = match args.parse::() { + Ok(t) => t, + Err(_) => { + msg.reply(&ctx.http, "Sorry I don't know who that is!") + .await?; + + return Ok(()); + } + }; + + args.advance(); + + let amount = args.parse::()?; + + let mut data = ctx.data.write().await; + let global_data = data.get_mut::().unwrap(); + + { + let author_wallet = get_user_wallet(&mut global_data.cfg, msg.author.id); + if author_wallet.coin_count < amount { + 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) + .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(()) +} diff --git a/src/discord/mod.rs b/src/discord/mod.rs index eb6cf61..ab8bff4 100644 --- a/src/discord/mod.rs +++ b/src/discord/mod.rs @@ -2,11 +2,14 @@ pub mod admin; pub mod album; pub mod celeryman; pub mod color; +pub mod fren_coin; pub mod joke; pub mod story; +use crate::discord::fren_coin::get_user_wallet; use crate::discord::joke::random; use crate::{help, hook, GlobalData}; +use rand::{thread_rng, Rng}; use serenity::async_trait; use serenity::client::Context; use serenity::framework::standard::{ @@ -75,7 +78,30 @@ pub async fn after( command_result: CommandResult, ) { match command_result { - Ok(()) => println!("Processed command '{}'", command_name), + Ok(()) => { + println!("Processed command '{}'", command_name); + + let give_coins = { + let mut rng = thread_rng(); + rng.gen_bool(0.10) + }; + + if give_coins { + let mut data = ctx.data.write().await; + let global_data = data.get_mut::().unwrap(); + + { + let wallet = get_user_wallet(&mut global_data.cfg, msg.author.id); + wallet.coin_count += 5; + } + + global_data + .cfg + .save(&global_data.args.cfg_path) + .await + .unwrap(); + } + } Err(why) => { println!("Command '{}' returned error {:?}", command_name, why); msg.reply( diff --git a/src/main.rs b/src/main.rs index 365d1e4..7bc63e2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,6 +40,7 @@ async fn main() { .group(&discord::joke::JOKE_GROUP) .group(&discord::admin::ADMIN_GROUP) .group(&discord::story::STORY_GROUP) + .group(&discord::fren_coin::FRENCOIN_GROUP) .unrecognised_command(unrecognised_command_hook) .bucket("bad_apple", |b| b.delay(60 * 10)) .await