botserv: bots join +ao (protected admin + op), keeping op alongside protect
All checks were successful
CI / check (push) Successful in 3m53s

This commit is contained in:
Jean Chevronnet 2026-07-17 17:11:25 +00:00
parent 73467b91ca
commit f2ba876ce4
No known key found for this signature in database
4 changed files with 12 additions and 11 deletions

View file

@ -444,9 +444,10 @@ impl Engine {
for (bot_lc, chan) in &desired {
if !self.bot_channels.contains(&(bot_lc.clone(), chan.clone())) {
if let Some(uid) = self.bot_uids.get(bot_lc) {
// BotServ bots join as protected admins (+a) so ordinary ops
// can't kick or deop them — the standard bot default.
out.push(NetAction::ServiceJoin { uid: uid.clone(), channel: chan.clone(), modes: "a".into() });
// BotServ bots join as protected admins + op (+ao) so they hold
// op and ordinary ops still can't kick or deop them — the
// standard bot default.
out.push(NetAction::ServiceJoin { uid: uid.clone(), channel: chan.clone(), modes: "ao".into() });
self.bot_channels.insert((bot_lc.clone(), chan.clone()));
}
}

View file

@ -2217,9 +2217,9 @@
ns(&mut e, "000AAAAAC", "IDENTIFY password1");
bs(&mut e, "000AAAAAC", "BOT ADD Bendy bot serv.host Helper"); // goes live
// The founder assigns the bot: it joins the channel as a protected admin (+a).
// The founder assigns the bot: it joins as a protected admin + op (+ao).
let out = bs(&mut e, "000AAAAAB", "ASSIGN #c Bendy");
assert!(out.iter().any(|a| matches!(a, NetAction::ServiceJoin { channel, modes, .. } if channel == "#c" && modes == "a")), "joins +a on assign: {out:?}");
assert!(out.iter().any(|a| matches!(a, NetAction::ServiceJoin { channel, modes, .. } if channel == "#c" && modes == "ao")), "joins +ao on assign: {out:?}");
// Unassigning parts it.
let out = bs(&mut e, "000AAAAAB", "UNASSIGN #c");
assert!(out.iter().any(|a| matches!(a, NetAction::ServicePart { channel, .. } if channel == "#c")), "parts on unassign: {out:?}");