add /ban, /allowentry, and /setpass commands, resolving #4

This commit is contained in:
Zoey 2024-04-23 21:45:49 -07:00
parent b76bb5bbc6
commit 5e8fe5a753
No known key found for this signature in database
GPG key ID: 8611B896D1AAFAF2
4 changed files with 149 additions and 10 deletions

10
Cargo.lock generated
View file

@ -108,6 +108,7 @@ dependencies = [
"flate2",
"half",
"internment",
"nanoid",
"optional_struct",
"parking_lot",
"rand",
@ -243,6 +244,15 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "nanoid"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8"
dependencies = [
"rand",
]
[[package]]
name = "num_cpus"
version = "1.16.0"

View file

@ -9,6 +9,7 @@ bytes = "1"
flate2 = "1"
half = "2"
internment = {version = "0.8", features = ["serde"]}
nanoid = "0.4"
optional_struct = "0.4"
parking_lot = "0.12"
rand = "0.8"

View file

@ -2,13 +2,26 @@ use crate::player::PlayerType;
const CMD_ME: &str = "me";
const CMD_SAY: &str = "say";
const CMD_SET_PERM: &str = "setperm";
const CMD_SETPERM: &str = "setperm";
const CMD_KICK: &str = "kick";
const CMD_STOP: &str = "stop";
const CMD_HELP: &str = "help";
const CMD_BAN: &str = "ban";
const CMD_ALLOWENTRY: &str = "allowentry";
const CMD_SETPASS: &str = "setpass";
/// list of commands available on the server
pub const COMMANDS_LIST: &[&str] = &[CMD_ME, CMD_SAY, CMD_SET_PERM, CMD_KICK, CMD_STOP, CMD_HELP];
pub const COMMANDS_LIST: &[&str] = &[
CMD_ME,
CMD_SAY,
CMD_SETPERM,
CMD_KICK,
CMD_STOP,
CMD_HELP,
CMD_BAN,
CMD_ALLOWENTRY,
CMD_SETPASS,
];
/// enum for possible commands
#[derive(Debug, Clone)]
@ -33,6 +46,18 @@ pub enum Command<'m> {
Stop,
/// gets help about the given command, or about all commands if no command is given
Help { command: Option<&'m str> },
/// bans a player from the server
Ban {
player_username: &'m str,
message: Option<&'m str>,
},
/// allows a player entry into the server
AllowEntry {
player_username: &'m str,
password: Option<&'m str>,
},
/// sets the current player's password
SetPass { password: &'m str },
}
impl<'m> Command<'m> {
@ -45,7 +70,7 @@ impl<'m> Command<'m> {
Ok(match command_name {
CMD_ME => Self::Me { action: arguments },
CMD_SAY => Self::Say { message: arguments },
CMD_SET_PERM => Self::SetPermissions {
CMD_SETPERM => Self::SetPermissions {
player_username: Self::next_string(&mut arguments)?,
permissions: arguments.trim().try_into()?,
},
@ -59,6 +84,27 @@ impl<'m> Command<'m> {
CMD_HELP => Self::Help {
command: (!arguments.is_empty()).then_some(arguments),
},
CMD_BAN => {
let player_username = Self::next_string(&mut arguments)?;
let message = arguments.trim();
let message = (!message.is_empty()).then_some(message);
Self::Ban {
player_username,
message,
}
}
CMD_ALLOWENTRY => {
let player_username = Self::next_string(&mut arguments)?;
let password = arguments.trim();
let password = (!password.is_empty()).then_some(password);
Self::AllowEntry {
player_username,
password,
}
}
CMD_SETPASS => Self::SetPass {
password: arguments.trim(),
},
_ => return Err(format!("Unknown command: {command_name}")),
})
}
@ -68,10 +114,13 @@ impl<'m> Command<'m> {
match self {
Self::Me { .. } => CMD_ME,
Self::Say { .. } => CMD_SAY,
Self::SetPermissions { .. } => CMD_SET_PERM,
Self::SetPermissions { .. } => CMD_SETPERM,
Self::Kick { .. } => CMD_KICK,
Self::Stop => CMD_STOP,
Self::Help { .. } => CMD_HELP,
Self::Ban { .. } => CMD_BAN,
Self::AllowEntry { .. } => CMD_ALLOWENTRY,
Self::SetPass { .. } => CMD_SETPASS,
}
}
@ -86,6 +135,7 @@ impl<'m> Command<'m> {
CMD_ME => PlayerType::Normal,
CMD_STOP => PlayerType::Operator,
CMD_HELP => PlayerType::Normal,
CMD_SETPASS => PlayerType::Normal,
_ => PlayerType::Moderator,
}
}
@ -103,7 +153,7 @@ impl<'m> Command<'m> {
c("<message>"),
"&fSends a message as being from the server.".to_string(),
],
CMD_SET_PERM => vec![
CMD_SETPERM => vec![
c("<username> <permission level>"),
"&fSets a player's permission level.".to_string(),
],
@ -119,6 +169,15 @@ impl<'m> Command<'m> {
c("[command]"),
"&fGets a list of commands or help about a command.".to_string(),
],
CMD_BAN => vec![
c("<username> [reason]"),
"&fBans a player from the server.".to_string(),
],
CMD_ALLOWENTRY => vec![
c("<username>"),
"&fAllows a player into the server.".to_string(),
],
CMD_SETPASS => vec![c("<new password>"), "&fUpdates your password.".to_string()],
_ => vec!["&eUnknown command!".to_string()],
}
}

View file

@ -455,11 +455,12 @@ async fn handle_stream_inner(
continue;
}
other_player.should_be_kicked = Some(
message
.unwrap_or("<no message>")
.to_string(),
);
other_player.should_be_kicked =
Some(format!(
"Kicked: {}",
message
.unwrap_or("<no message>")
));
msg!(format!(
"{} has been kicked",
other_player.username
@ -517,6 +518,74 @@ async fn handle_stream_inner(
msg!(msg);
}
}
Command::Ban {
player_username,
message,
} => {
let player_perms = player.permissions;
if let ServerProtectionMode::PasswordsByUser(passwords) = &mut data.config.protection_mode {
if !passwords.contains_key(player_username) {
msg!("&cPlayer is already banned!".to_string());
} else {
passwords.remove(player_username);
data.config.player_perms.remove(player_username);
data.config_needs_saving = true;
if let Some(other_player) =
data.players.iter_mut().find(|p| {
p.username == player_username
}) {
if player_perms
<= other_player.permissions
{
msg!("&cThis player outranks or is the same rank as you".to_string());
continue;
}
other_player.should_be_kicked =
Some(format!("Banned: {}", message.unwrap_or("<no_message>")));
}
msg!(format!(
"{} has been banned",
player_username
));
}
} else {
msg!("&cServer must be set to per-user passwords!".to_string());
}
}
Command::AllowEntry {
player_username,
password,
} => {
if let ServerProtectionMode::PasswordsByUser(passwords) = &mut data.config.protection_mode {
if passwords.contains_key(player_username) {
msg!("&cPlayer is already allowed in the server!".to_string());
} else {
let password = password.map(|p| p.to_string()).unwrap_or_else(|| {
nanoid::nanoid!()
});
msg!(format!("{player_username} is now allowed in the server."));
msg!(format!("Password: {password}"));
passwords.insert(player_username.to_string(), password);
data.config_needs_saving = true;
}
} else {
msg!("&cServer must be set to per-user passwords!".to_string());
}
}
Command::SetPass { password } => {
let username = player.username.clone();
if let ServerProtectionMode::PasswordsByUser(passwords) = &mut data.config.protection_mode {
passwords.insert(username, password.to_string());
data.config_needs_saving = true;
msg!("Updated password!".to_string());
} else {
msg!("&cServer must be set to per-user passwords!".to_string());
}
}
}
}
Err(msg) => {