chanserv: SET PEACE (block acting against equal-or-higher access)

PEACE stops a channel op from using ChanServ KICK/BAN/DEOP/DEVOICE against
someone whose access rank (founder>op>voice) is equal to or above their own.
Adds a typed access_rank on ChannelView and a peace_blocks guard in those
commands. Same typed-settings path as SIGNKICK/PRIVATE; shown in INFO.
This commit is contained in:
Jean Chevronnet 2026-07-13 03:06:58 +00:00
parent 75019c867a
commit 3bf6b2be77
No known key found for this signature in database
7 changed files with 62 additions and 2 deletions

View file

@ -104,6 +104,7 @@ impl Service for ChanServ {
let mut opts = Vec::new();
if info.signkick { opts.push("SIGNKICK"); }
if info.private { opts.push("PRIVATE"); }
if info.peace { opts.push("PEACE"); }
if !opts.is_empty() {
ctx.notice(me, from.uid, format!(" Options : {}", opts.join(", ")));
}
@ -235,6 +236,20 @@ fn require_op(me: &str, from: &Sender, chan: &str, ctx: &mut ServiceCtx, db: &dy
}
}
// PEACE: returns true (and notices) if `from` may not act against `target_uid`
// because the channel has PEACE set and the target holds equal-or-higher access.
fn peace_blocks(me: &str, from: &Sender, chan: &str, target_uid: &str, ctx: &mut ServiceCtx, net: &dyn NetView, db: &dyn Store) -> bool {
let Some(info) = db.channel(chan) else { return false };
if !info.peace {
return false;
}
if info.access_rank(net.account_of(target_uid)) >= info.access_rank(from.account) {
ctx.notice(me, from.uid, "\x02PEACE\x02 is set: you can't act against someone with equal or higher access.");
return true;
}
false
}
// Parse a mode spec like "+nt-s" into (locked-on, locked-off) mode chars. `r` is
// implicit for a registered channel and is ignored here.
fn parse_mlock(spec: &str) -> (String, String) {