BotServ kickers: caps + formatting, with DONTKICKOPS

The assigned bot now enforces kickers on channel lines: KICK <#channel>
CAPS ON [min [percent]], and BOLDS/COLORS/UNDERLINES/REVERSES/ITALICS
for control-code formatting. DONTKICKOPS exempts channel operators. A
tripping line is kicked by the bot itself.

Kicker config is a typed KickerSettings struct on the channel (event-
sourced like ChanSettings) with a violation() check; the engine runs it
on every channel PRIVMSG. Factored the founder-or-admin gate into a
shared require_channel_admin helper (assign/set/kick).
This commit is contained in:
Jean Chevronnet 2026-07-13 14:54:14 +00:00
parent ad8041bd9d
commit ed7da9c713
No known key found for this signature in database
8 changed files with 310 additions and 21 deletions

View file

@ -403,6 +403,19 @@ pub enum ChanSetting {
BotGreet,
}
// A BotServ kicker: the assigned bot kicks a message that trips an enabled one.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Kicker {
Caps,
Bolds,
Colors,
Underlines,
Reverses,
Italics,
// Exemption, not a rule: never kick channel operators.
DontKickOps,
}
impl ChannelView {
// The channel mode this account is entitled to on join (+o founder/op, +v
// voice), or None if it holds no access.
@ -534,6 +547,8 @@ pub trait Store {
fn set_mlock(&mut self, name: &str, on: &str, off: &str) -> Result<(), ChanError>;
fn set_desc(&mut self, channel: &str, desc: &str) -> Result<(), ChanError>;
fn set_channel_setting(&mut self, channel: &str, setting: ChanSetting, on: bool) -> Result<(), ChanError>;
fn set_kicker(&mut self, channel: &str, kicker: Kicker, on: bool) -> Result<(), ChanError>;
fn set_caps_kicker(&mut self, channel: &str, caps_min: u16, caps_percent: u16) -> Result<(), ChanError>;
fn set_channel_topic(&mut self, channel: &str, topic: &str) -> Result<(), ChanError>;
fn suspend_channel(&mut self, channel: &str, by: &str, reason: &str, expires: Option<u64>) -> Result<(), ChanError>;
fn unsuspend_channel(&mut self, channel: &str) -> Result<bool, ChanError>;