use async_trait::async_trait; use reqwest::Method; use serenity::builder::CreateApplicationCommand; use serenity::model::interactions::application_command::{ ApplicationCommandInteraction, ApplicationCommandOptionType, }; use geoffrey_models::models::locations::Location; use geoffrey_models::models::parameters::add_item_params::AddItemParams; use geoffrey_models::models::response::api_error::GeoffreyAPIError; use crate::bot::arg_parse::{option_to_i64, option_to_string}; use crate::bot::commands::BotCommand; use crate::bot::formatters::GeoffreyFormatter; use crate::bot::lang::{PLAYER_ALREADY_SELLS_ITEM, PLAYER_DOES_NOT_HAVE_MATCHING_SHOP}; use crate::context::GeoffreyContext; use crate::error::BotError; use serenity::utils::MessageBuilder; pub struct AddItemCommand; #[async_trait] impl BotCommand for AddItemCommand { type ApiParams = AddItemParams; type ApiResp = Location; fn command_name() -> String { "add_item".to_string() } fn request_type() -> Method { Method::POST } fn custom_err_resp(e: &BotError) -> Option { match e { BotError::GeoffreyApi(GeoffreyAPIError::EntryNotFound) => { Some(PLAYER_DOES_NOT_HAVE_MATCHING_SHOP.to_string()) } BotError::GeoffreyApi(GeoffreyAPIError::EntryNotUnique) => { Some(PLAYER_ALREADY_SELLS_ITEM.to_string()) } _ => None, } } fn create_app_command(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand { command .name(Self::command_name()) .description("Add a item to a shop.") .create_option(|option| { option .name("shop") .description("Shop to list the item at") .kind(ApplicationCommandOptionType::String) .required(true) }) .create_option(|option| { option .name("item_name") .description("Name of the item to sell.") .kind(ApplicationCommandOptionType::String) .required(true) }) .create_option(|option| { option .name("price") .description("Price to list them item at.") .kind(ApplicationCommandOptionType::Integer) .required(true) .min_int_value(0) }) .create_option(|option| { option .name("quantity") .description("Number of items to sell for price") .kind(ApplicationCommandOptionType::Integer) .required(true) .min_int_value(1) }) } async fn process_arguments( command_interaction: ApplicationCommandInteraction, ) -> Result { let options = command_interaction.data.options; Ok(Self::ApiParams::new( option_to_string(options.get(1), "item_name")?, option_to_i64(options.get(2), "price")? as u32, option_to_i64(options.get(3), "quantity")? as u32, option_to_string(options.get(0), "shop")?, )) } fn build_response(ctx: &GeoffreyContext, resp: Self::ApiResp, req: Self::ApiParams) -> String { GeoffreyFormatter::new(ctx.settings.clone()) .push( &MessageBuilder::new() .push_bold_safe(req.item_name) .push(" has been added to ") .push_line(&resp.name) .build(), ) .push_loc_full(&resp) .build() } }