feat: Completed commands list
- Added MapError::CannotReach variant - Updated Map::unlock_room_for_account to check reachableness - Added /info command - Added /unlock command - Added /move command - Added /reset command
This commit is contained in:
parent
4ba57b925a
commit
b6ea2d8958
11 changed files with 170 additions and 12 deletions
|
|
@ -10,6 +10,6 @@ clap = { version = "4.5.53", features = ["derive"] }
|
|||
dotenvy = "0.15.7"
|
||||
poise = "0.6.1"
|
||||
serde = "1.0.228"
|
||||
squad-quest = { version = "0.8.0", path = ".." }
|
||||
squad-quest = { version = "0.9.0", path = ".." }
|
||||
tokio = { version = "1.48.0", features = ["rt-multi-thread"] }
|
||||
toml = "0.9.8"
|
||||
|
|
|
|||
|
|
@ -40,6 +40,34 @@ fn account_user_id(account: &Account) -> UserId {
|
|||
UserId::new(account.id.clone().parse::<u64>().expect("automatically inserted"))
|
||||
}
|
||||
|
||||
#[poise::command(
|
||||
prefix_command,
|
||||
slash_command,
|
||||
guild_only,
|
||||
required_permissions = "ADMINISTRATOR",
|
||||
)]
|
||||
pub async fn reset(
|
||||
ctx: Context<'_>,
|
||||
who: UserId,
|
||||
) -> Result<(), Error> {
|
||||
let accounts = ctx.data().config.load_accounts();
|
||||
|
||||
let acc_id = format!("{}", who.get());
|
||||
|
||||
if let None = accounts.iter().find(|a| a.id == acc_id) {
|
||||
return Err(Error::AccountNotFound);
|
||||
}
|
||||
|
||||
let mut path = ctx.data().config.full_accounts_path();
|
||||
path.push(format!("{acc_id}.toml"));
|
||||
Account::delete(path)?;
|
||||
|
||||
let reply_string = "User was successfully reset.".to_string();
|
||||
ctx.reply(reply_string).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[poise::command(
|
||||
prefix_command,
|
||||
slash_command,
|
||||
|
|
|
|||
67
discord/src/commands/map.rs
Normal file
67
discord/src/commands/map.rs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
use squad_quest::{SquadObject, map::Map};
|
||||
|
||||
use crate::{Context, account::fetch_or_init_account, error::Error};
|
||||
|
||||
#[poise::command(
|
||||
prefix_command,
|
||||
slash_command,
|
||||
guild_only,
|
||||
)]
|
||||
pub async fn unlock(
|
||||
ctx: Context<'_>,
|
||||
id: u16,
|
||||
) -> Result<(), Error> {
|
||||
let conf = &ctx.data().config;
|
||||
|
||||
let map_path = conf.full_map_path();
|
||||
let map = Map::load(map_path)?;
|
||||
|
||||
let Some(room) = map.room.iter().find(|r| r.id == id) else {
|
||||
return Err(Error::RoomNotFound(id));
|
||||
};
|
||||
|
||||
let acc_id = format!("{}", ctx.author().id.get());
|
||||
let mut account = fetch_or_init_account(conf, acc_id);
|
||||
|
||||
if account.balance < room.value {
|
||||
return Err(Error::InsufficientFunds(room.value));
|
||||
}
|
||||
|
||||
map.unlock_room_for_account(id, &mut account)?;
|
||||
|
||||
let account_path = conf.full_accounts_path();
|
||||
account.save(account_path)?;
|
||||
|
||||
let reply_string = format!("Unlocked room #{id}. Your balance: {} points", account.balance);
|
||||
ctx.reply(reply_string).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[poise::command(
|
||||
prefix_command,
|
||||
slash_command,
|
||||
guild_only,
|
||||
)]
|
||||
pub async fn r#move(
|
||||
ctx: Context<'_>,
|
||||
id: u16,
|
||||
) -> Result<(), Error> {
|
||||
let conf = &ctx.data().config;
|
||||
|
||||
let acc_id = format!("{}", ctx.author().id.get());
|
||||
let mut account = fetch_or_init_account(conf, acc_id);
|
||||
|
||||
if let None = account.rooms_unlocked.iter().find(|rid| **rid == id) {
|
||||
return Err(Error::RoomNotFound(id));
|
||||
}
|
||||
|
||||
account.location = id;
|
||||
let account_path = conf.full_accounts_path();
|
||||
account.save(account_path)?;
|
||||
|
||||
let reply_string = format!("Moved to room #{id}.");
|
||||
ctx.reply(reply_string).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ pub mod init;
|
|||
pub mod answer;
|
||||
pub mod social;
|
||||
pub mod account;
|
||||
pub mod map;
|
||||
|
||||
#[poise::command(prefix_command)]
|
||||
pub async fn register(ctx: Context<'_>) -> Result<(), Error> {
|
||||
|
|
@ -15,6 +16,21 @@ pub async fn register(ctx: Context<'_>) -> Result<(), Error> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[poise::command(
|
||||
prefix_command,
|
||||
slash_command,
|
||||
)]
|
||||
pub async fn info(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let reply_string = format!("\
|
||||
SquadQuest version {ver}\n\
|
||||
Find the map here: {url}",
|
||||
ver = env!("CARGO_PKG_VERSION"),
|
||||
url = "not implemented yet!",
|
||||
);
|
||||
ctx.say(reply_string).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn error_handler(error: poise::FrameworkError<'_, Data, Error>) {
|
||||
eprintln!("ERROR:");
|
||||
print_error_recursively(&error);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use poise::serenity_prelude as serenity;
|
||||
use squad_quest::error::MapError;
|
||||
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug)]
|
||||
|
|
@ -15,6 +16,9 @@ pub enum Error {
|
|||
SquadQuestError(squad_quest::error::Error),
|
||||
AccountNotFound,
|
||||
InsufficientFunds(u32),
|
||||
RoomNotFound(u16),
|
||||
RoomAlreadyUnlocked(u16),
|
||||
CannotReach(u16),
|
||||
}
|
||||
|
||||
impl From<serenity::Error> for Error {
|
||||
|
|
@ -29,6 +33,18 @@ impl From<squad_quest::error::Error> for Error {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<squad_quest::error::MapError> for Error {
|
||||
fn from(value: squad_quest::error::MapError) -> Self {
|
||||
match value {
|
||||
MapError::RoomNotFound(id) => Self::RoomNotFound(id),
|
||||
MapError::RoomAlreadyUnlocked(id, _) => Self::RoomAlreadyUnlocked(id),
|
||||
MapError::InsufficientFunds(_, _, amount) => Self::InsufficientFunds(amount),
|
||||
MapError::CannotReach(id, _) => Self::CannotReach(id),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
|
|
@ -41,7 +57,10 @@ impl Display for Error {
|
|||
Self::SerenityError(_) => write!(f, "discord interaction error"),
|
||||
Self::SquadQuestError(_) => write!(f, "internal logic error"),
|
||||
Self::AccountNotFound => write!(f, "account not found"),
|
||||
Self::InsufficientFunds(amount) => write!(f, "account does not have {amount} points"),
|
||||
Self::InsufficientFunds(amount) => write!(f, "user does not have {amount} points"),
|
||||
Self::RoomNotFound(id) => write!(f, "room #{id} not found"),
|
||||
Self::RoomAlreadyUnlocked(id) => write!(f, "room #{id} is already unlocked for this user"),
|
||||
Self::CannotReach(id) => write!(f, "user cannot reach room #{id}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -56,7 +75,10 @@ impl std::error::Error for Error {
|
|||
Self::NoChannelOrUser |
|
||||
Self::BothChannelAndUser |
|
||||
Self::AccountNotFound |
|
||||
Self::InsufficientFunds(_) => None,
|
||||
Self::InsufficientFunds(_) |
|
||||
Self::RoomNotFound(_) |
|
||||
Self::RoomAlreadyUnlocked(_) |
|
||||
Self::CannotReach(_) => None,
|
||||
Self::SerenityError(error) => Some(error),
|
||||
Self::SquadQuestError(error) => Some(error),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,11 +42,15 @@ async fn main() {
|
|||
commands: vec![
|
||||
commands::quest::quest(),
|
||||
commands::register(),
|
||||
commands::info(),
|
||||
commands::init::init(),
|
||||
commands::answer::answer(),
|
||||
commands::social::social(),
|
||||
commands::account::scoreboard(),
|
||||
commands::account::balance(),
|
||||
commands::account::reset(),
|
||||
commands::map::unlock(),
|
||||
commands::map::r#move(),
|
||||
],
|
||||
..Default::default()
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue