BotServ kickers: times-to-ban (TTB) + BANEXPIRE
KICK <#channel> TTB <n> makes the bot ban a user after they've been kicked n times (by any kicker) instead of only kicking; SET <#channel> BANEXPIRE <duration|off> controls how long that ban lasts. One clear per-channel knob rather than Anope's per-kicker ttb array. The kick count rides in the existing ephemeral per-user chatter state, so it's dropped when the user parts or quits. On the ban the bot sets +b on an ideal host mask and, if BANEXPIRE is set, queues an unban that is swept off the next event — no timer thread. Ban time is injectable for tests.
This commit is contained in:
parent
ca95184359
commit
ec3205bf75
5 changed files with 225 additions and 63 deletions
|
|
@ -331,6 +331,13 @@ pub struct KickerSettings {
|
|||
// Kick lines matching one of the channel's badword regexes.
|
||||
#[serde(default)]
|
||||
pub badwords: bool,
|
||||
// Times a user may be kicked (by any kicker) before the bot bans them
|
||||
// instead. 0 = never ban, only kick.
|
||||
#[serde(default)]
|
||||
pub ttb: u16,
|
||||
// How long such a ban lasts, in seconds. 0 = until manually removed.
|
||||
#[serde(default)]
|
||||
pub ban_expire: u32,
|
||||
// Don't kick channel operators, whatever they send.
|
||||
#[serde(default)]
|
||||
pub dontkickops: bool,
|
||||
|
|
@ -799,7 +806,7 @@ impl Db {
|
|||
if let Some(bot) = &c.assigned_bot {
|
||||
snapshot.push(Event::ChannelBotAssigned { channel: c.name.clone(), bot: bot.clone() });
|
||||
}
|
||||
if c.kickers.any() || c.kickers.dontkickops {
|
||||
if c.kickers.any() || c.kickers.dontkickops || c.kickers.ttb > 0 || c.kickers.ban_expire > 0 {
|
||||
snapshot.push(Event::ChannelKickerSet { channel: c.name.clone(), kickers: c.kickers.clone() });
|
||||
}
|
||||
if !c.badwords.is_empty() {
|
||||
|
|
@ -1447,6 +1454,16 @@ impl Db {
|
|||
})
|
||||
}
|
||||
|
||||
/// Kicks-before-ban threshold (0 = never ban, only kick).
|
||||
pub fn set_ttb(&mut self, channel: &str, ttb: u16) -> Result<(), ChanError> {
|
||||
self.update_kickers(channel, |k| k.ttb = ttb)
|
||||
}
|
||||
|
||||
/// How long a kicker ban lasts, in seconds (0 = until removed).
|
||||
pub fn set_ban_expire(&mut self, channel: &str, secs: u32) -> Result<(), ChanError> {
|
||||
self.update_kickers(channel, |k| k.ban_expire = secs)
|
||||
}
|
||||
|
||||
/// Add a badword regex. Validates it compiles within the size limit; returns
|
||||
/// Ok(false) if the exact pattern is already present.
|
||||
pub fn badword_add(&mut self, channel: &str, pattern: &str) -> Result<bool, ChanError> {
|
||||
|
|
@ -2092,6 +2109,12 @@ impl Store for Db {
|
|||
fn set_repeat_kicker(&mut self, channel: &str, times: u16) -> Result<(), ChanError> {
|
||||
Db::set_repeat_kicker(self, channel, times)
|
||||
}
|
||||
fn set_ttb(&mut self, channel: &str, ttb: u16) -> Result<(), ChanError> {
|
||||
Db::set_ttb(self, channel, ttb)
|
||||
}
|
||||
fn set_ban_expire(&mut self, channel: &str, secs: u32) -> Result<(), ChanError> {
|
||||
Db::set_ban_expire(self, channel, secs)
|
||||
}
|
||||
fn badword_add(&mut self, channel: &str, pattern: &str) -> Result<bool, ChanError> {
|
||||
Db::badword_add(self, channel, pattern)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue