Add corp management commands.

This commit is contained in:
Condorra 2023-03-26 16:51:10 +11:00
parent cd0f9661d1
commit 6c86599103
2 changed files with 189 additions and 3 deletions

View File

@ -846,6 +846,14 @@ impl DBTrans {
Ok(CorpId(id)) Ok(CorpId(id))
} }
pub async fn update_corp_details(&self, corp: &CorpId, details: &Corp) -> DResult<()> {
self.pg_trans()?
.execute("UPDATE corps SET details=$1 WHERE corp_id = $2",
&[&serde_json::to_value(details)?, &corp.0]
).await?;
Ok(())
}
pub async fn expire_old_invites(&self) -> DResult<()> { pub async fn expire_old_invites(&self) -> DResult<()> {
self.pg_trans()? self.pg_trans()?
.execute( .execute(

View File

@ -81,6 +81,7 @@ async fn corp_invite(ctx: &mut VerbContext<'_>, remaining: &str) -> UResult<()>
let new_mem = CorpMembership { let new_mem = CorpMembership {
invited_at: Some(Utc::now()), invited_at: Some(Utc::now()),
allow_combat: corp.allow_combat_required, allow_combat: corp.allow_combat_required,
permissions: corp.member_permissions.clone(),
..Default::default() ..Default::default()
}; };
ctx.trans.upsert_corp_membership(&corp_id, &target_user.item_code, &new_mem).await?; ctx.trans.upsert_corp_membership(&corp_id, &target_user.item_code, &new_mem).await?;
@ -221,6 +222,10 @@ async fn corp_fire(ctx: &mut VerbContext<'_>, remaining: &str) -> UResult<()> {
if target_user.item_type != "player" { if target_user.item_type != "player" {
user_error("Only players can be fired.".to_owned())?; user_error("Only players can be fired.".to_owned())?;
} }
if target_user.item_code == player.item_code {
user_error("Fire yourself? You know you can just resign right?".to_owned())?;
}
match ctx.trans.match_user_corp_by_name(into_raw.trim(), &target_user.item_code).await? { match ctx.trans.match_user_corp_by_name(into_raw.trim(), &target_user.item_code).await? {
None => user_error(format!( None => user_error(format!(
@ -358,6 +363,7 @@ async fn corp_promote(ctx: &mut VerbContext<'_>, remaining: &str) -> UResult<()>
} }
} }
} }
if !mem.permissions.contains(&CorpPermission::Holder) && if !mem.permissions.contains(&CorpPermission::Holder) &&
!(&perm_add | &perm_rem).is_subset(&mem.permissions.clone().into_iter().collect()) { !(&perm_add | &perm_rem).is_subset(&mem.permissions.clone().into_iter().collect()) {
user_error("You can only change permissions you have yourself.".to_owned())? user_error("You can only change permissions you have yourself.".to_owned())?
@ -398,11 +404,34 @@ async fn corp_info(ctx: &mut VerbContext<'_>, remaining: &str) -> UResult<()> {
std::time::Duration::from_secs( std::time::Duration::from_secs(
(Utc::now() - corp.founded).num_seconds() as u64)); (Utc::now() - corp.founded).num_seconds() as u64));
msg.push_str(&format!(ansi!("<bold>{}'s essential information<reset>\nFounded: {} ago\n"), msg.push_str(&format!(ansi!("<bold>{}'s essential information<reset>\nFounded: {} ago\n"),
&corp.name, &founded_ago)); &corp.name, &founded_ago));
let members = ctx.trans.list_corp_members(&corp_id).await?;
if corp.allow_combat_required {
msg.push_str("Members ARE required to allow the corp to consent to fighting on their behalf");
let tot_mem = members.len();
let mem_allow_combat = members.iter().filter(|(_, m)| m.allow_combat).count();
if tot_mem == mem_allow_combat {
msg.push_str(", and all members have done so.\n");
} else {
msg.push_str("- waiting on the following members to do so: ");
for (u, _) in members.iter().filter(|(_, m)| !m.allow_combat) {
msg.push_str(&caps_first(&u));
msg.push(' ');
}
msg.push('\n');
}
} else {
msg.push_str("Members are NOT required to allow the corp to consent to fighting on their behalf.\n");
}
msg.push_str(&format!("Base member privileges: {}\n",
&corp.member_permissions.iter().map(|p| p.display())
.join(" ")));
msg.push_str("Members:\n"); msg.push_str("Members:\n");
msg.push_str(&format!(ansi!("<bgblue><white><bold>| {:20} | {:20} | {:20} |<reset>\n"), "Name", "Title", "Permissions" msg.push_str(&format!(ansi!("<bgblue><white><bold>| {:20} | {:20} | {:20} |<reset>\n"), "Name", "Title", "Privileges"
)); ));
for (user, mem) in ctx.trans.list_corp_members(&corp_id).await? { for (user, mem) in members {
msg.push_str( msg.push_str(
&format!(ansi!("| {:20} | {:20} | {:20} |\n"), &format!(ansi!("| {:20} | {:20} | {:20} |\n"),
caps_first(&user), caps_first(&user),
@ -417,6 +446,136 @@ async fn corp_info(ctx: &mut VerbContext<'_>, remaining: &str) -> UResult<()> {
Ok(()) Ok(())
} }
async fn corp_allow_combat(ctx: &mut VerbContext<'_>, remaining: &str) -> UResult<()> {
let (command, remaining) = parse_command_name(remaining);
if command != "from" {
user_error("Usage: corp allow combat from corpname".to_owned())?;
}
let user = get_user_or_fail(ctx)?;
let (corp_id, corp, mut mem) =
match ctx.trans.match_user_corp_by_name(remaining.trim(), &user.username).await? {
None => user_error("You don't seem to belong to a matching corp!".to_owned())?,
Some(c) => c
};
if mem.allow_combat {
user_error(format!("You already allow combat for {}.", &corp.name))?;
}
mem.allow_combat = true;
ctx.trans.upsert_corp_membership(&corp_id, &user.username.to_lowercase(), &mem).await?;
ctx.trans.queue_for_session(
&ctx.session,
Some("You now allow the corp to consent to fighting on your behalf.\n")).await?;
Ok(())
}
async fn corp_disallow_combat(ctx: &mut VerbContext<'_>, remaining: &str) -> UResult<()> {
let (command, remaining) = parse_command_name(remaining);
if command != "from" {
user_error("Usage: corp disallow combat from corpname".to_owned())?
}
let user = get_user_or_fail(ctx)?;
let (corp_id, corp, mut mem) =
match ctx.trans.match_user_corp_by_name(remaining.trim(), &user.username).await? {
None => user_error("You don't seem to belong to a matching corp!".to_owned())?,
Some(c) => c
};
if !mem.allow_combat {
user_error("You already disallow combat for that corp.".to_owned())?;
}
if corp.allow_combat_required {
user_error(format!(ansi!("That corp requires everyone to allow combat as a condition \
of employment, so you can't do that. You could do \
<bold>corp resign {}<reset> instead."),
&corp.name)
)?;
}
mem.allow_combat = false;
ctx.trans.upsert_corp_membership(&corp_id, &user.username.to_lowercase(), &mem).await?;
ctx.trans.queue_for_session(
&ctx.session,
Some("You no longer allow the corp to consent to fighting on your behalf.\n")).await?;
Ok(())
}
async fn corp_config(ctx: &mut VerbContext<'_>, remaining: &str) -> UResult<()> {
let (corp_name_raw, remaining) = match remaining.split_once(" ") {
None => user_error("Usage: corp config corpname ...".to_owned())?,
Some(v) => v
};
let remaining = remaining.trim().to_lowercase();
let user = get_user_or_fail(ctx)?;
let (corp_id, mut corp, mem) =
match ctx.trans.match_user_corp_by_name(corp_name_raw.trim(), &user.username).await? {
None => user_error("You don't seem to belong to a matching corp!".to_owned())?,
Some(c) => c
};
if !check_corp_perm(&CorpPermission::Configure, &mem) {
user_error("You don't have permission to change settings for that corp.".to_owned())?;
}
if remaining == "allow combat required" {
corp.allow_combat_required = true;
ctx.trans.broadcast_to_corp(
&corp_id,
&CorpCommType::Notice, None,
&format!("{} announces a policy decision for {}: all new members must allow the \
corp to consent to fights on their behalf.\n",
&caps_first(&user.username),
&corp.name)).await?;
ctx.trans.update_corp_details(&corp_id, &corp).await?;
} else if remaining == "allow combat not required" {
corp.allow_combat_required = false;
ctx.trans.update_corp_details(&corp_id, &corp).await?;
ctx.trans.broadcast_to_corp(
&corp_id,
&CorpCommType::Notice, None,
&format!("{} announces a policy decision for {}: new members no longer need to allow the \
corp to consent to fights on their behalf. Any member can now use \
\"corp disallow combat from {}\" if they want to.\n",
&caps_first(&user.username),
&corp.name, &corp.name)).await?;
} else if remaining.starts_with("base privileges ") {
let remaining = remaining[("base privileges ".len())..].trim();
let psplit = remaining.split(" ");
let mut perms: BTreeSet<CorpPermission> = BTreeSet::new();
for perm in psplit {
let perm = ignore_special_characters(&perm.trim()).to_lowercase();
if perm == "none" {
continue;
}
let perm = match CorpPermission::parse(&perm) {
None => user_error(format!("Unknown permission {}", perm))?,
Some(p) if p == CorpPermission::Holder =>
user_error("You can't set holder as a base privilege.".to_owned())?,
Some(p) if !check_corp_perm(&p, &mem) =>
user_error("You can't set base privilege you don't have yourself."
.to_owned())?,
Some(p) => p
};
perms.insert(perm);
}
corp.member_permissions = perms.clone().into_iter().collect();
let perm_str = &corp.member_permissions.iter().map(|p| p.display()).join(" ");
ctx.trans.broadcast_to_corp(
&corp_id,
&CorpCommType::Notice, None,
&format!("{} announces a policy decision for {}: new members get \
the following privileges: {}.\n",
&caps_first(&user.username),
&corp.name,
if perm_str == "" { "none" } else { &perm_str }
)).await?;
ctx.trans.update_corp_details(&corp_id, &corp).await?;
} else {
user_error("Configurations you can set:\n\tallow combat required\n\tallow combat not required\nbase permissions permission_name permission_name".to_owned())?;
}
Ok(())
}
pub struct Verb; pub struct Verb;
#[async_trait] #[async_trait]
impl UserVerb for Verb { impl UserVerb for Verb {
@ -430,6 +589,25 @@ impl UserVerb for Verb {
"fire" | "dismiss" => corp_fire(ctx, remaining).await?, "fire" | "dismiss" => corp_fire(ctx, remaining).await?,
"promote" | "demote" => corp_promote(ctx, remaining).await?, "promote" | "demote" => corp_promote(ctx, remaining).await?,
"info" => corp_info(ctx, remaining).await?, "info" => corp_info(ctx, remaining).await?,
"allow" => {
let (command, remaining) = parse_command_name(remaining);
if command.to_lowercase() != "combat" {
user_error("Allow must be followed with combat".to_owned())?
} else {
corp_allow_combat(ctx, remaining).await?
}
},
"disallow" => {
let (command, remaining) = parse_command_name(remaining);
if command.to_lowercase() != "combat" {
user_error("Disallow must be followed with combat".to_owned())?
} else {
corp_disallow_combat(ctx, remaining).await?
}
},
"configure" | "config" => {
corp_config(ctx, remaining).await?;
}
_ => user_error("Unknown command".to_owned())? _ => user_error("Unknown command".to_owned())?
} }
Ok(()) Ok(())