136 lines
4.4 KiB
Rust
136 lines
4.4 KiB
Rust
use std::fmt::Debug;
|
|
use std::future::Future;
|
|
use std::pin::Pin;
|
|
|
|
use async_trait::async_trait;
|
|
use serde::de::DeserializeOwned;
|
|
use serde::Serialize;
|
|
use serenity::builder::CreateApplicationCommand;
|
|
use serenity::model::interactions::application_command::ApplicationCommandInteraction;
|
|
|
|
use geoffrey_models::models::parameters::{CommandRequest, GeoffreyParam};
|
|
use geoffrey_models::models::player::UserID;
|
|
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
|
|
|
use crate::api::run_api_query;
|
|
use crate::context::GeoffreyContext;
|
|
use crate::error::BotError;
|
|
|
|
pub mod add_item;
|
|
pub mod add_location;
|
|
pub mod delete;
|
|
pub mod edit_name;
|
|
pub mod edit_pos;
|
|
pub mod find;
|
|
pub mod info;
|
|
pub mod register;
|
|
pub mod remove_item;
|
|
pub mod report_out_of_stock;
|
|
pub mod restock;
|
|
pub mod selling;
|
|
pub mod set_portal;
|
|
|
|
pub type GeoffreyCommandFn = Box<
|
|
fn(
|
|
GeoffreyContext,
|
|
UserID,
|
|
ApplicationCommandInteraction,
|
|
) -> Pin<Box<dyn Future<Output = String> + Send>>,
|
|
>;
|
|
|
|
#[async_trait]
|
|
pub trait BotCommand: Send + 'static {
|
|
type ApiParams: GeoffreyParam;
|
|
type ApiResp: Serialize + DeserializeOwned + Send + Debug;
|
|
|
|
fn command_name() -> String;
|
|
|
|
fn endpoint() -> String {
|
|
format!("command/{}/", Self::command_name())
|
|
}
|
|
|
|
fn request_type() -> reqwest::Method;
|
|
|
|
fn get_err_resp(err: BotError) -> String {
|
|
if let Some(resp) = Self::custom_err_resp(&err) {
|
|
resp
|
|
} else {
|
|
match err {
|
|
BotError::GeoffreyApi(GeoffreyAPIError::PlayerNotRegistered) => {
|
|
"You need to register before using this command!".to_string()
|
|
}
|
|
BotError::GeoffreyApi(GeoffreyAPIError::EntryNotFound) => {
|
|
"Couldn't find that, maybe look for something that exists?".to_string()
|
|
}
|
|
BotError::GeoffreyApi(GeoffreyAPIError::PermissionInsufficient) => {
|
|
"Looks like you don't have permission for that.".to_string()
|
|
}
|
|
BotError::GeoffreyApi(GeoffreyAPIError::EntryNotUnique) => {
|
|
"Slow down, I already know that thing. Try a new name.".to_string()
|
|
}
|
|
BotError::GeoffreyApi(GeoffreyAPIError::MultipleLocationsMatch) => {
|
|
"I couldn't match a single location, narrow down your search".to_string()
|
|
}
|
|
BotError::GeoffreyApi(GeoffreyAPIError::ParameterInvalid(err)) => {
|
|
format!(
|
|
"Welp, you some how messed up the {} parameter, great job",
|
|
err
|
|
)
|
|
}
|
|
_ => {
|
|
log::warn!("GeoffreyBot got an unhandled error: {}", err);
|
|
format!("OOPSIE WOOPSIE!! Uwu We made a fucky wucky!! A wittle fucko boingo! The admins at our \
|
|
headquarters are working VEWY HAWD to fix this! (Error in command {})", Self::command_name())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn custom_err_resp(_: &BotError) -> Option<String> {
|
|
None
|
|
}
|
|
|
|
fn create_app_command(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand;
|
|
|
|
async fn process_arguments(
|
|
command_interaction: ApplicationCommandInteraction,
|
|
) -> Result<Self::ApiParams, BotError>;
|
|
|
|
async fn run_command(
|
|
ctx: GeoffreyContext,
|
|
user_id: UserID,
|
|
command_interact: ApplicationCommandInteraction,
|
|
) -> Result<String, BotError> {
|
|
let args = Self::process_arguments(command_interact).await?;
|
|
|
|
log::info!(
|
|
"Running command {}, with args {:?}",
|
|
Self::command_name(),
|
|
args
|
|
);
|
|
|
|
let request = CommandRequest {
|
|
token: ctx.cfg.api.token.clone(),
|
|
user_id: Some(user_id),
|
|
params: args.clone(),
|
|
};
|
|
|
|
let resp = run_api_query(&ctx, &request, Self::request_type(), &Self::endpoint()).await?;
|
|
|
|
Ok(Self::build_response(&ctx, resp, args))
|
|
}
|
|
|
|
async fn command(
|
|
ctx: GeoffreyContext,
|
|
user_id: UserID,
|
|
command_interact: ApplicationCommandInteraction,
|
|
) -> String {
|
|
match Self::run_command(ctx, user_id, command_interact).await {
|
|
Ok(msg) => msg,
|
|
Err(e) => Self::get_err_resp(e),
|
|
}
|
|
}
|
|
|
|
fn build_response(ctx: &GeoffreyContext, resp: Self::ApiResp, req: Self::ApiParams) -> String;
|
|
}
|