Moved bot inventory to the db
+ Refactored item and shop handling a bit + fmt + clippy
This commit is contained in:
parent
f9776218e0
commit
362977caa9
@ -1,7 +1,6 @@
|
|||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::imgur;
|
use crate::imgur;
|
||||||
use crate::imgur::Image;
|
use crate::imgur::Image;
|
||||||
use crate::inventory::InventoryManager;
|
|
||||||
use config::{Config, File};
|
use config::{Config, File};
|
||||||
use j_db::database::Database;
|
use j_db::database::Database;
|
||||||
use rand::prelude::SliceRandom;
|
use rand::prelude::SliceRandom;
|
||||||
@ -44,8 +43,6 @@ pub struct BotConfig {
|
|||||||
pub db_path: PathBuf,
|
pub db_path: PathBuf,
|
||||||
pub admins: Vec<UserId>,
|
pub admins: Vec<UserId>,
|
||||||
|
|
||||||
pub bot_inventory: InventoryManager,
|
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub albums: Vec<AlbumConfig>,
|
pub albums: Vec<AlbumConfig>,
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::config::{Channel, GlobalData};
|
use crate::config::{Channel, GlobalData};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::user::{give_funds, try_take_funds, UserError};
|
use crate::user::{User, UserError};
|
||||||
use crate::{command, group};
|
use crate::{command, group};
|
||||||
use rand::seq::IteratorRandom;
|
use rand::seq::IteratorRandom;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
@ -133,7 +133,7 @@ async fn add_bet(
|
|||||||
|
|
||||||
let global = data.get_mut::<GlobalData>().unwrap();
|
let global = data.get_mut::<GlobalData>().unwrap();
|
||||||
|
|
||||||
try_take_funds(&global.db, bet.author, bet.amount).map_err(|err| match err {
|
User::try_take_funds(&global.db, bet.author, bet.amount).map_err(|err| match err {
|
||||||
Error::UserError(e) => RaceError::BetFundError(e),
|
Error::UserError(e) => RaceError::BetFundError(e),
|
||||||
_ => panic!("Recv'ed error when trying to bet: {}", err),
|
_ => panic!("Recv'ed error when trying to bet: {}", err),
|
||||||
})?;
|
})?;
|
||||||
@ -296,7 +296,7 @@ async fn race(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
|
|||||||
winner_msg.mention(&winner);
|
winner_msg.mention(&winner);
|
||||||
winner_msg.push_line("");
|
winner_msg.push_line("");
|
||||||
|
|
||||||
give_funds(&global_data.db, winner, payout as u32)?;
|
User::give_funds(&global_data.db, winner, payout as u32)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::config::GlobalData;
|
use crate::config::GlobalData;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::user::{get_user, give_funds, transfer_funds, UserError};
|
use crate::user::{User, UserError};
|
||||||
use crate::{command, group};
|
use crate::{command, group};
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use serenity::client::Context;
|
use serenity::client::Context;
|
||||||
@ -23,7 +23,7 @@ async fn balance(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
|||||||
|
|
||||||
let user = args.parse::<UserId>().unwrap_or(msg.author.id);
|
let user = args.parse::<UserId>().unwrap_or(msg.author.id);
|
||||||
|
|
||||||
let wallet = get_user(&global_data.db, user)?;
|
let wallet = User::get_user(&global_data.db, user)?;
|
||||||
|
|
||||||
msg.reply(
|
msg.reply(
|
||||||
&ctx.http,
|
&ctx.http,
|
||||||
@ -72,7 +72,7 @@ async fn gift(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
|||||||
let mut data = ctx.data.write().await;
|
let mut data = ctx.data.write().await;
|
||||||
let global_data = data.get_mut::<GlobalData>().unwrap();
|
let global_data = data.get_mut::<GlobalData>().unwrap();
|
||||||
|
|
||||||
if let Err(e) = transfer_funds(&global_data.db, msg.author.id, target, amount) {
|
if let Err(e) = User::transfer_funds(&global_data.db, msg.author.id, target, amount) {
|
||||||
if let Error::UserError(UserError::NotEnoughFunds) = e {
|
if let Error::UserError(UserError::NotEnoughFunds) = e {
|
||||||
msg.reply(
|
msg.reply(
|
||||||
&ctx.http,
|
&ctx.http,
|
||||||
@ -116,7 +116,7 @@ pub async fn give_coin(
|
|||||||
let mut data = ctx.data.write().await;
|
let mut data = ctx.data.write().await;
|
||||||
let global_data = data.get_mut::<GlobalData>().unwrap();
|
let global_data = data.get_mut::<GlobalData>().unwrap();
|
||||||
|
|
||||||
give_funds(&global_data.db, user, number_of_coins as u32)?;
|
User::give_funds(&global_data.db, user, number_of_coins as u32)?;
|
||||||
|
|
||||||
global_data
|
global_data
|
||||||
.cfg
|
.cfg
|
||||||
|
|||||||
@ -77,7 +77,7 @@ pub fn render_random(
|
|||||||
|
|
||||||
Ok(tera::Tera::one_off(
|
Ok(tera::Tera::one_off(
|
||||||
template,
|
template,
|
||||||
&tera::Context::from_serialize(&random_ctx)?,
|
&tera::Context::from_serialize(random_ctx)?,
|
||||||
false,
|
false,
|
||||||
)?)
|
)?)
|
||||||
}
|
}
|
||||||
@ -153,7 +153,7 @@ pub async fn add_random(ctx: &Context, msg: &Message, mut args: Args) -> Command
|
|||||||
#[command]
|
#[command]
|
||||||
#[example("8ball Funny Response haha")]
|
#[example("8ball Funny Response haha")]
|
||||||
pub async fn list_random(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
pub async fn list_random(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||||
if args.len() < 1 {
|
if args.is_empty() {
|
||||||
msg.reply(
|
msg.reply(
|
||||||
&ctx.http,
|
&ctx.http,
|
||||||
"Look kid, you need to provide both the random name",
|
"Look kid, you need to provide both the random name",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::discord::motivate::create_image;
|
use crate::discord::motivate::create_image;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::inventory::{InventoryError, ItemData, ItemType};
|
use crate::inventory::{InventoryError, ItemData, ItemType, Operation};
|
||||||
use crate::user::{get_user, give_item, try_take_funds, try_use_item, UserError};
|
use crate::user::{User, UserError};
|
||||||
use crate::{command, group, GlobalData};
|
use crate::{command, group, GlobalData};
|
||||||
use rand::prelude::SliceRandom;
|
use rand::prelude::SliceRandom;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
@ -23,7 +23,9 @@ async fn shop(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
|
|||||||
let mut data = ctx.data.write().await;
|
let mut data = ctx.data.write().await;
|
||||||
let global_data = data.get_mut::<GlobalData>().unwrap();
|
let global_data = data.get_mut::<GlobalData>().unwrap();
|
||||||
|
|
||||||
if global_data.cfg.bot_inventory.inventory.is_empty() {
|
let bot_user = User::get_user(&global_data.db, ctx.cache.current_user_id())?;
|
||||||
|
|
||||||
|
if bot_user.inventory.inventory.is_empty() {
|
||||||
msg.reply(&ctx.http, "Sorry shop is closed until we get more wares.")
|
msg.reply(&ctx.http, "Sorry shop is closed until we get more wares.")
|
||||||
.await?;
|
.await?;
|
||||||
} else {
|
} else {
|
||||||
@ -31,7 +33,7 @@ async fn shop(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
|
|||||||
|
|
||||||
inv_msg.push_bold_line("Fren has wares if you have coin:");
|
inv_msg.push_bold_line("Fren has wares if you have coin:");
|
||||||
|
|
||||||
inv_msg.push_safe(global_data.cfg.bot_inventory.list_items(true));
|
inv_msg.push_safe(bot_user.inventory.list_items(true));
|
||||||
|
|
||||||
msg.reply(&ctx.http, inv_msg.build()).await?;
|
msg.reply(&ctx.http, inv_msg.build()).await?;
|
||||||
}
|
}
|
||||||
@ -47,7 +49,7 @@ async fn inventory(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
|
|||||||
|
|
||||||
let mut inv_msg = MessageBuilder::new();
|
let mut inv_msg = MessageBuilder::new();
|
||||||
|
|
||||||
let user = get_user(&global_data.db, msg.author.id)?;
|
let user = User::get_user(&global_data.db, msg.author.id)?;
|
||||||
|
|
||||||
if user.inventory.inventory.is_empty() {
|
if user.inventory.inventory.is_empty() {
|
||||||
msg.reply(&ctx, "Sorry your inventory is empty.").await?;
|
msg.reply(&ctx, "Sorry your inventory is empty.").await?;
|
||||||
@ -86,37 +88,30 @@ async fn buy(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(item_slot) = global_data.cfg.bot_inventory.get_item(item) {
|
let res = User::item_transaction(
|
||||||
if let Err(err) = try_take_funds(&global_data.db, msg.author.id, item_slot.value() as u32) {
|
&global_data.db,
|
||||||
msg.reply(
|
ctx.cache.current_user_id(),
|
||||||
&ctx.http,
|
msg.author.id,
|
||||||
format!(
|
item,
|
||||||
"I see why you don't get to the cloud district very often: {}",
|
Operation::Buy,
|
||||||
err
|
);
|
||||||
),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
msg.reply(&ctx.http, "I don't have that in stock you goob")
|
|
||||||
.await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let item_data = match global_data.cfg.bot_inventory.try_take_item(item, 1) {
|
if let Err(err) = res {
|
||||||
Ok(i) => i,
|
if let Error::UserError(err) = err {
|
||||||
Err(err) => {
|
let resp = match err {
|
||||||
msg.reply(&ctx.http, format!("I can't just sell you that: {}", err))
|
UserError::NotEnoughFunds => "Sorry Link, but I can't give store credit. Come back when you are mhhmm richer.".to_string(),
|
||||||
.await?;
|
UserError::InvalidTarget => "I don't know who you are or how you got here.".to_string(),
|
||||||
return Ok(());
|
UserError::InventoryError(err) => format!("Something went wrong with that item: {}", err)
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
give_item(&global_data.db, msg.author.id, item, 1, item_data)?;
|
msg.reply(&ctx.http, resp).await?;
|
||||||
|
} else {
|
||||||
|
return Err(err.into());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
msg.reply(&ctx, format!("Congrats, you now own a '{}'", item))
|
msg.reply(&ctx, format!("Congrats, you now own a '{}'", item))
|
||||||
.await?;
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -144,7 +139,7 @@ async fn use_item(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let item_data = match try_use_item(&global_data.db, msg.author.id, item) {
|
let item_data = match User::try_use_item(&global_data.db, msg.author.id, item) {
|
||||||
Ok(i) => i,
|
Ok(i) => i,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if let Error::UserError(UserError::InventoryError(InventoryError::NotEnoughItems)) = err
|
if let Error::UserError(UserError::InventoryError(InventoryError::NotEnoughItems)) = err
|
||||||
@ -227,19 +222,19 @@ pub async fn restock_shop(ctx: &Context) -> Result<(), CommandError> {
|
|||||||
let mut data = ctx.data.write().await;
|
let mut data = ctx.data.write().await;
|
||||||
let global_data = data.get_mut::<GlobalData>().unwrap();
|
let global_data = data.get_mut::<GlobalData>().unwrap();
|
||||||
|
|
||||||
global_data.cfg.bot_inventory.inventory.clear();
|
let mut bot_user = User::get_user(&global_data.db, ctx.cache.current_user_id())?;
|
||||||
|
|
||||||
global_data.cfg.bot_inventory.give_item(
|
bot_user.inventory.inventory.clear();
|
||||||
|
|
||||||
|
bot_user.inventory.give_item(
|
||||||
ItemType::TheConceptOfLove,
|
ItemType::TheConceptOfLove,
|
||||||
thread_rng().gen_range(0..5),
|
thread_rng().gen_range(0..5),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
global_data.cfg.bot_inventory.give_item(
|
bot_user
|
||||||
ItemType::GoodFortune,
|
.inventory
|
||||||
thread_rng().gen_range(0..10),
|
.give_item(ItemType::GoodFortune, thread_rng().gen_range(0..10), None);
|
||||||
None,
|
bot_user.inventory.give_item(
|
||||||
);
|
|
||||||
global_data.cfg.bot_inventory.give_item(
|
|
||||||
ItemType::CancelInsurance,
|
ItemType::CancelInsurance,
|
||||||
thread_rng().gen_range(0..10),
|
thread_rng().gen_range(0..10),
|
||||||
None,
|
None,
|
||||||
@ -272,7 +267,7 @@ pub async fn restock_shop(ctx: &Context) -> Result<(), CommandError> {
|
|||||||
let mut file = tokio::fs::File::create(path.clone()).await?;
|
let mut file = tokio::fs::File::create(path.clone()).await?;
|
||||||
file.write_all(&nft).await?;
|
file.write_all(&nft).await?;
|
||||||
|
|
||||||
global_data.cfg.bot_inventory.give_item(
|
bot_user.inventory.give_item(
|
||||||
ItemType::Nft,
|
ItemType::Nft,
|
||||||
1,
|
1,
|
||||||
Some(ItemData::Nft(path.to_str().unwrap().to_string())),
|
Some(ItemData::Nft(path.to_str().unwrap().to_string())),
|
||||||
@ -280,7 +275,7 @@ pub async fn restock_shop(ctx: &Context) -> Result<(), CommandError> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
global_data.cfg.save(&global_data.args.cfg_path).await?;
|
global_data.db.insert::<User>(bot_user)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,14 @@ pub enum ItemType {
|
|||||||
Nft,
|
Nft,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Hash, Eq, PartialEq, Copy)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum Operation {
|
||||||
|
Sell,
|
||||||
|
Buy,
|
||||||
|
Custom(i64),
|
||||||
|
}
|
||||||
|
|
||||||
impl FromStr for ItemType {
|
impl FromStr for ItemType {
|
||||||
type Err = InventoryError;
|
type Err = InventoryError;
|
||||||
|
|
||||||
@ -117,7 +125,7 @@ pub struct InventoryManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl InventoryManager {
|
impl InventoryManager {
|
||||||
pub fn get_item(&mut self, item_type: ItemType) -> Option<&mut InventorySlot> {
|
pub fn get_item_mut(&mut self, item_type: ItemType) -> Option<&mut InventorySlot> {
|
||||||
if let Some(inv_ndx) = self.inventory.iter().position(|i| i.item_type == item_type) {
|
if let Some(inv_ndx) = self.inventory.iter().position(|i| i.item_type == item_type) {
|
||||||
Some(&mut self.inventory[inv_ndx])
|
Some(&mut self.inventory[inv_ndx])
|
||||||
} else {
|
} else {
|
||||||
@ -125,8 +133,16 @@ impl InventoryManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_item(&self, item_type: ItemType) -> Option<&InventorySlot> {
|
||||||
|
if let Some(inv_ndx) = self.inventory.iter().position(|i| i.item_type == item_type) {
|
||||||
|
Some(&self.inventory[inv_ndx])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn give_item(&mut self, item_type: ItemType, quantity: i64, item_data: Option<ItemData>) {
|
pub fn give_item(&mut self, item_type: ItemType, quantity: i64, item_data: Option<ItemData>) {
|
||||||
match self.get_item(item_type) {
|
match self.get_item_mut(item_type) {
|
||||||
None => self.inventory.push(InventorySlot {
|
None => self.inventory.push(InventorySlot {
|
||||||
quantity,
|
quantity,
|
||||||
item_type,
|
item_type,
|
||||||
@ -144,7 +160,7 @@ impl InventoryManager {
|
|||||||
item: ItemType,
|
item: ItemType,
|
||||||
quantity: i64,
|
quantity: i64,
|
||||||
) -> Result<Option<ItemData>, InventoryError> {
|
) -> Result<Option<ItemData>, InventoryError> {
|
||||||
let slot = self.get_item(item);
|
let slot = self.get_item_mut(item);
|
||||||
|
|
||||||
if let Some(slot) = slot {
|
if let Some(slot) = slot {
|
||||||
if slot.quantity < quantity {
|
if slot.quantity < quantity {
|
||||||
@ -179,7 +195,9 @@ impl InventoryManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_use_item(&mut self, item: ItemType) -> Result<Option<ItemData>, InventoryError> {
|
pub fn try_use_item(&mut self, item: ItemType) -> Result<Option<ItemData>, InventoryError> {
|
||||||
let item_slot = self.get_item(item).ok_or(InventoryError::NotEnoughItems)?;
|
let item_slot = self
|
||||||
|
.get_item_mut(item)
|
||||||
|
.ok_or(InventoryError::NotEnoughItems)?;
|
||||||
|
|
||||||
if item_slot.quantity < item_slot.use_cost() {
|
if item_slot.quantity < item_slot.use_cost() {
|
||||||
return Err(InventoryError::NotEnoughItems);
|
return Err(InventoryError::NotEnoughItems);
|
||||||
|
|||||||
238
src/user/mod.rs
238
src/user/mod.rs
@ -1,5 +1,5 @@
|
|||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::inventory::{InventoryError, InventoryManager, ItemData, ItemType};
|
use crate::inventory::{InventoryError, InventoryManager, ItemData, ItemType, Operation};
|
||||||
use j_db::database::Database;
|
use j_db::database::Database;
|
||||||
use j_db::model::JdbModel;
|
use j_db::model::JdbModel;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -39,6 +39,7 @@ pub struct User {
|
|||||||
pub inventory: InventoryManager,
|
pub inventory: InventoryManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
impl User {
|
impl User {
|
||||||
pub fn new(user_id: UserId) -> Self {
|
pub fn new(user_id: UserId) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -48,6 +49,147 @@ impl User {
|
|||||||
inventory: Default::default(),
|
inventory: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_user(db: &Database, discord_id: UserId) -> Result<User, Error> {
|
||||||
|
let user: Option<User> = db
|
||||||
|
.filter(|_, user: &User| user.user_id == discord_id)?
|
||||||
|
.next();
|
||||||
|
|
||||||
|
let user = match user {
|
||||||
|
None => db.insert::<User>(User::new(discord_id))?,
|
||||||
|
Some(user) => user,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn transfer_funds(
|
||||||
|
db: &Database,
|
||||||
|
src: UserId,
|
||||||
|
dest: UserId,
|
||||||
|
amount: u32,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
Self::try_take_funds(db, src, amount)?;
|
||||||
|
|
||||||
|
Self::give_funds(db, dest, amount)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn give_funds(db: &Database, discord_id: UserId, amount: u32) -> Result<(), Error> {
|
||||||
|
let mut wallet = Self::get_user(db, discord_id)?;
|
||||||
|
wallet.coin_count += amount as i64;
|
||||||
|
|
||||||
|
db.insert::<User>(wallet)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_take_funds(db: &Database, discord_id: UserId, amount: u32) -> Result<(), Error> {
|
||||||
|
let mut wallet = Self::get_user(db, discord_id)?;
|
||||||
|
if wallet.coin_count < amount as i64 {
|
||||||
|
return Err(UserError::NotEnoughFunds.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
wallet.coin_count -= amount as i64;
|
||||||
|
|
||||||
|
db.insert::<User>(wallet)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn give_item(
|
||||||
|
db: &Database,
|
||||||
|
discord_id: UserId,
|
||||||
|
item: ItemType,
|
||||||
|
quantity: i64,
|
||||||
|
item_data: Option<ItemData>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let mut user = Self::get_user(db, discord_id)?;
|
||||||
|
|
||||||
|
user.inventory.give_item(item, quantity, item_data);
|
||||||
|
|
||||||
|
db.insert::<User>(user)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn try_take_item(
|
||||||
|
db: &Database,
|
||||||
|
discord_id: UserId,
|
||||||
|
item: ItemType,
|
||||||
|
quantity: i64,
|
||||||
|
) -> Result<Option<ItemData>, Error> {
|
||||||
|
let mut user = Self::get_user(db, discord_id)?;
|
||||||
|
|
||||||
|
let item = user
|
||||||
|
.inventory
|
||||||
|
.try_take_item(item, quantity)
|
||||||
|
.map_err(UserError::InventoryError)?;
|
||||||
|
|
||||||
|
db.insert::<User>(user)?;
|
||||||
|
|
||||||
|
Ok(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_use_item(
|
||||||
|
db: &Database,
|
||||||
|
discord_id: UserId,
|
||||||
|
item: ItemType,
|
||||||
|
) -> Result<Option<ItemData>, Error> {
|
||||||
|
let mut user = Self::get_user(db, discord_id)?;
|
||||||
|
|
||||||
|
let item = user
|
||||||
|
.inventory
|
||||||
|
.try_use_item(item)
|
||||||
|
.map_err(UserError::InventoryError)?;
|
||||||
|
|
||||||
|
db.insert::<User>(user)?;
|
||||||
|
|
||||||
|
Ok(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn item_transaction(
|
||||||
|
db: &Database,
|
||||||
|
seller_id: UserId,
|
||||||
|
buyer_id: UserId,
|
||||||
|
item: ItemType,
|
||||||
|
operation: Operation,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let mut seller = Self::get_user(db, seller_id)?;
|
||||||
|
let mut buyer = Self::get_user(db, buyer_id)?;
|
||||||
|
|
||||||
|
if seller.inventory.get_item(item).is_none() {
|
||||||
|
return Err(UserError::from(InventoryError::NotEnoughItems).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let item = seller.inventory.get_item_mut(item).unwrap();
|
||||||
|
|
||||||
|
let price = match operation {
|
||||||
|
Operation::Sell => item.sell_value(),
|
||||||
|
Operation::Buy => item.value(),
|
||||||
|
Operation::Custom(p) => p,
|
||||||
|
};
|
||||||
|
|
||||||
|
if buyer.coin_count < price {
|
||||||
|
return Err(UserError::NotEnoughFunds.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
buyer.coin_count -= price;
|
||||||
|
|
||||||
|
buyer
|
||||||
|
.inventory
|
||||||
|
.give_item(item.item_type, 1, item.item_data.clone());
|
||||||
|
|
||||||
|
item.quantity -= 1;
|
||||||
|
item.item_data = None;
|
||||||
|
|
||||||
|
seller.coin_count += price;
|
||||||
|
|
||||||
|
db.insert::<User>(seller)?;
|
||||||
|
db.insert::<User>(buyer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JdbModel for User {
|
impl JdbModel for User {
|
||||||
@ -63,97 +205,3 @@ impl JdbModel for User {
|
|||||||
"Users".to_string()
|
"Users".to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_user(db: &Database, discord_id: UserId) -> Result<User, Error> {
|
|
||||||
let user: Option<User> = db
|
|
||||||
.filter(|_, user: &User| user.user_id == discord_id)?
|
|
||||||
.next();
|
|
||||||
|
|
||||||
let user = match user {
|
|
||||||
None => db.insert::<User>(User::new(discord_id))?,
|
|
||||||
Some(user) => user,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(user)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn transfer_funds(db: &Database, src: UserId, dest: UserId, amount: u32) -> Result<(), Error> {
|
|
||||||
try_take_funds(db, src, amount)?;
|
|
||||||
|
|
||||||
give_funds(db, dest, amount)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn give_funds(db: &Database, discord_id: UserId, amount: u32) -> Result<(), Error> {
|
|
||||||
let mut wallet = get_user(db, discord_id)?;
|
|
||||||
wallet.coin_count += amount as i64;
|
|
||||||
|
|
||||||
db.insert::<User>(wallet)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn try_take_funds(db: &Database, discord_id: UserId, amount: u32) -> Result<(), Error> {
|
|
||||||
let mut wallet = get_user(db, discord_id)?;
|
|
||||||
if wallet.coin_count < amount as i64 {
|
|
||||||
return Err(UserError::NotEnoughFunds.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
wallet.coin_count -= amount as i64;
|
|
||||||
|
|
||||||
db.insert::<User>(wallet)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn give_item(
|
|
||||||
db: &Database,
|
|
||||||
discord_id: UserId,
|
|
||||||
item: ItemType,
|
|
||||||
quantity: i64,
|
|
||||||
item_data: Option<ItemData>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let mut user = get_user(db, discord_id)?;
|
|
||||||
|
|
||||||
user.inventory.give_item(item, quantity, item_data);
|
|
||||||
|
|
||||||
db.insert::<User>(user)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn try_take_item(
|
|
||||||
db: &Database,
|
|
||||||
discord_id: UserId,
|
|
||||||
item: ItemType,
|
|
||||||
quantity: i64,
|
|
||||||
) -> Result<Option<ItemData>, Error> {
|
|
||||||
let mut user = get_user(db, discord_id)?;
|
|
||||||
|
|
||||||
let item = user
|
|
||||||
.inventory
|
|
||||||
.try_take_item(item, quantity)
|
|
||||||
.map_err(UserError::InventoryError)?;
|
|
||||||
|
|
||||||
db.insert::<User>(user)?;
|
|
||||||
|
|
||||||
Ok(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn try_use_item(
|
|
||||||
db: &Database,
|
|
||||||
discord_id: UserId,
|
|
||||||
item: ItemType,
|
|
||||||
) -> Result<Option<ItemData>, Error> {
|
|
||||||
let mut user = get_user(db, discord_id)?;
|
|
||||||
|
|
||||||
let item = user
|
|
||||||
.inventory
|
|
||||||
.try_use_item(item)
|
|
||||||
.map_err(UserError::InventoryError)?;
|
|
||||||
|
|
||||||
db.insert::<User>(user)?;
|
|
||||||
|
|
||||||
Ok(item)
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user