Added restock command
continuous-integration/woodpecker the build was successful
Details
continuous-integration/woodpecker the build was successful
Details
+ Discord command has not been tested + Clippy + Fmtmain
parent
ec8926d693
commit
928e59a700
|
@ -441,6 +441,7 @@ name = "geoffrey_bot"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
"config",
|
||||
"geoffrey_models",
|
||||
"log",
|
||||
|
|
|
@ -7,6 +7,7 @@ use crate::commands::info::InfoCommand;
|
|||
use crate::commands::link::LinkCommand;
|
||||
use crate::commands::register::Register;
|
||||
use crate::commands::remove_item::RemoveItem;
|
||||
use crate::commands::restock::Restock;
|
||||
use crate::commands::selling::Selling;
|
||||
use crate::commands::set_portal::SetPortal;
|
||||
use crate::config::GeoffreyAPIConfig;
|
||||
|
@ -36,6 +37,7 @@ pub mod info;
|
|||
pub mod link;
|
||||
pub mod register;
|
||||
pub mod remove_item;
|
||||
pub mod restock;
|
||||
pub mod selling;
|
||||
pub mod set_portal;
|
||||
|
||||
|
@ -144,6 +146,7 @@ pub fn command_filter(
|
|||
.or(create_command_filter::<Edit>(ctx.clone()))
|
||||
.or(create_command_filter::<RemoveItem>(ctx.clone()))
|
||||
.or(create_command_filter::<InfoCommand>(ctx.clone()))
|
||||
.or(create_command_filter::<Restock>(ctx.clone()))
|
||||
.or(create_command_filter::<SetPortal>(ctx)),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
use crate::commands::{Command, RequestType};
|
||||
use crate::context::Context;
|
||||
use crate::Result;
|
||||
use geoffrey_db::helper::{find_location_by_name_type, load_location};
|
||||
use geoffrey_models::models::item::ItemListing;
|
||||
use geoffrey_models::models::locations::{Location, LocationDataDb, LocationType};
|
||||
use geoffrey_models::models::parameters::restock_params::RestockParameters;
|
||||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use geoffrey_models::models::CommandLevel;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct Restock {}
|
||||
|
||||
impl Command for Restock {
|
||||
type Req = RestockParameters;
|
||||
type Resp = Location;
|
||||
|
||||
fn command_name() -> String {
|
||||
"restock".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> RequestType {
|
||||
RequestType::POST
|
||||
}
|
||||
|
||||
fn command_level() -> CommandLevel {
|
||||
CommandLevel::REGISTERED
|
||||
}
|
||||
|
||||
fn run_command(ctx: Arc<Context>, req: &Self::Req, user: Option<Player>) -> Result<Self::Resp> {
|
||||
let user = user.unwrap();
|
||||
|
||||
let mut shop = find_location_by_name_type(
|
||||
&ctx.db,
|
||||
&req.shop_name,
|
||||
user.id.unwrap(),
|
||||
LocationType::Shop,
|
||||
)?;
|
||||
|
||||
if let LocationDataDb::Shop(shop_data) = &mut shop.loc_data {
|
||||
let filter = regex::Regex::new(&req.item_name)
|
||||
.map_err(|_| GeoffreyAPIError::ParameterInvalid("item_name".to_string()))?;
|
||||
|
||||
let updated_items: HashSet<ItemListing> = shop_data
|
||||
.item_listings
|
||||
.iter()
|
||||
.map(|item| {
|
||||
let mut item = item.clone();
|
||||
if filter.is_match(&item.item.name) {
|
||||
item.restock();
|
||||
}
|
||||
|
||||
item
|
||||
})
|
||||
.collect();
|
||||
|
||||
shop_data.item_listings = updated_items;
|
||||
let shop = ctx.db.insert(shop)?;
|
||||
|
||||
load_location(&ctx.db, &shop).map_err(|err| err.into())
|
||||
} else {
|
||||
Err(GeoffreyAPIError::EntryNotFound)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ async-trait = "0.1.51"
|
|||
config = "0.11.0"
|
||||
structopt = "0.3.21"
|
||||
log = "0.4.14"
|
||||
chrono = "0.4.19"
|
||||
|
||||
# Doing this for now, as there seems to be an issue with using timestamps
|
||||
[dependencies.simple_logger]
|
||||
|
|
|
@ -26,6 +26,7 @@ pub mod find;
|
|||
pub mod info;
|
||||
pub mod register;
|
||||
pub mod remove_item;
|
||||
pub mod restock;
|
||||
pub mod selling;
|
||||
pub mod set_portal;
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ impl BotCommand for RemoveItemCommand {
|
|||
.create_option(|option| {
|
||||
option
|
||||
.name("shop_name")
|
||||
.description("Shop to list the item at")
|
||||
.description("Shop remove an item")
|
||||
.kind(ApplicationCommandOptionType::String)
|
||||
.required(true)
|
||||
})
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
use async_trait::async_trait;
|
||||
use reqwest::Method;
|
||||
use serenity::model::interactions::application_command::{
|
||||
ApplicationCommandInteraction, ApplicationCommandOptionType,
|
||||
};
|
||||
|
||||
use geoffrey_models::models::locations::Location;
|
||||
|
||||
use crate::bot::arg_parse::option_to_string;
|
||||
use crate::bot::commands::{BotCommand, CommandError};
|
||||
use crate::bot::formatters::display_loc_full;
|
||||
use crate::bot::lang::PLAYER_DOES_NOT_HAVE_MATCHING_SHOP;
|
||||
use geoffrey_models::models::parameters::restock_params::RestockParameters;
|
||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||
use serenity::builder::CreateApplicationCommand;
|
||||
|
||||
pub struct RestockCommand;
|
||||
|
||||
#[async_trait]
|
||||
impl BotCommand for RestockCommand {
|
||||
type ApiParams = RestockParameters;
|
||||
type ApiResp = Location;
|
||||
|
||||
fn command_name() -> String {
|
||||
"restock".to_string()
|
||||
}
|
||||
|
||||
fn request_type() -> Method {
|
||||
Method::POST
|
||||
}
|
||||
|
||||
fn custom_err_resp(e: &CommandError) -> Option<String> {
|
||||
match e {
|
||||
CommandError::GeoffreyApi(GeoffreyAPIError::EntryNotFound) => {
|
||||
Some(PLAYER_DOES_NOT_HAVE_MATCHING_SHOP.to_string())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn create_app_command(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand {
|
||||
command
|
||||
.name(Self::command_name())
|
||||
.description("Restock an item from a shop")
|
||||
.create_option(|option| {
|
||||
option
|
||||
.name("shop_name")
|
||||
.description("Shop to restock the item at")
|
||||
.kind(ApplicationCommandOptionType::String)
|
||||
.required(true)
|
||||
})
|
||||
.create_option(|option| {
|
||||
option
|
||||
.name("item_name")
|
||||
.description("Name of the item to restock")
|
||||
.kind(ApplicationCommandOptionType::String)
|
||||
.required(true)
|
||||
})
|
||||
}
|
||||
|
||||
async fn process_arguments(
|
||||
command_interaction: ApplicationCommandInteraction,
|
||||
) -> Result<Self::ApiParams, CommandError> {
|
||||
let options = command_interaction.data.options;
|
||||
|
||||
Ok(Self::ApiParams::new(
|
||||
option_to_string(options.get(0), "shop_name")?,
|
||||
option_to_string(options.get(1), "item_name")?,
|
||||
))
|
||||
}
|
||||
|
||||
fn build_response(resp: Self::ApiResp) -> String {
|
||||
format!(
|
||||
"**{}** has been updated:\n{}",
|
||||
resp.name,
|
||||
display_loc_full(&resp)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
use chrono::{Duration, Utc};
|
||||
use geoffrey_models::models::item::ItemListing;
|
||||
use geoffrey_models::models::locations::{Location, LocationData};
|
||||
use geoffrey_models::models::player::Player;
|
||||
use geoffrey_models::models::Portal;
|
||||
|
@ -54,6 +56,23 @@ pub fn display_loc(loc: &Location) -> String {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn display_item_listing(listing: &ItemListing) -> String {
|
||||
let stocked_diff = Utc::now() - listing.restocked_time;
|
||||
|
||||
let time_str = if stocked_diff < Duration::days(1) {
|
||||
"today".to_string()
|
||||
} else if stocked_diff < Duration::days(2) {
|
||||
"1 day ago".to_string()
|
||||
} else {
|
||||
format!("{} days ago", stocked_diff.num_days())
|
||||
};
|
||||
|
||||
format!(
|
||||
"**{}**, {} for {}D. Restocked {}.",
|
||||
listing.item.name, listing.count_per_price, listing.price, time_str
|
||||
)
|
||||
}
|
||||
|
||||
pub fn display_loc_full(loc: &Location) -> String {
|
||||
let info = match &loc.loc_data {
|
||||
LocationData::Shop(shop) => {
|
||||
|
@ -62,12 +81,7 @@ pub fn display_loc_full(loc: &Location) -> String {
|
|||
"\n**Inventory**:\n{}",
|
||||
shop.item_listings
|
||||
.iter()
|
||||
.map(|item| {
|
||||
format!(
|
||||
"**{}**, {} for {}D",
|
||||
item.item.name, item.count_per_price, item.price
|
||||
)
|
||||
})
|
||||
.map(display_item_listing)
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n")
|
||||
)
|
||||
|
|
|
@ -7,6 +7,7 @@ use crate::bot::commands::edit_pos::EditPosCommand;
|
|||
use crate::bot::commands::info::InfoCommand;
|
||||
use crate::bot::commands::register::RegisterCommand;
|
||||
use crate::bot::commands::remove_item::RemoveItemCommand;
|
||||
use crate::bot::commands::restock::RestockCommand;
|
||||
use crate::bot::commands::GeoffreyCommandFn;
|
||||
use crate::context::GeoffreyContext;
|
||||
use commands::add_item::AddItemCommand;
|
||||
|
@ -101,6 +102,8 @@ pub async fn build_commands(
|
|||
.add_command::<RemoveItemCommand>(ctx)
|
||||
.await?
|
||||
.add_command::<InfoCommand>(ctx)
|
||||
.await?
|
||||
.add_command::<RestockCommand>(ctx)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -8,6 +8,7 @@ pub mod info_params;
|
|||
pub mod link_params;
|
||||
pub mod register_params;
|
||||
pub mod remove_item_params;
|
||||
pub mod restock_params;
|
||||
pub mod selling_params;
|
||||
pub mod set_portal_params;
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
use crate::models::parameters::GeoffreyParam;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct RestockParameters {
|
||||
pub shop_name: String,
|
||||
pub item_name: String,
|
||||
}
|
||||
|
||||
impl RestockParameters {
|
||||
pub fn new(shop_name: String, item_name: String) -> Self {
|
||||
Self {
|
||||
shop_name,
|
||||
item_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GeoffreyParam for RestockParameters {}
|
Loading…
Reference in New Issue